summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java2
-rw-r--r--cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java2
-rw-r--r--cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java2
-rw-r--r--core/api/current.txt1
-rw-r--r--core/api/test-current.txt3
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java4
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java10
-rw-r--r--core/java/android/app/ActivityManager.java3
-rw-r--r--core/java/android/app/Notification.java4
-rw-r--r--core/java/android/app/NotificationManager.java15
-rw-r--r--core/java/android/app/TaskInfo.java2
-rw-r--r--core/java/android/content/pm/ActivityInfo.java28
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java6
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java4
-rw-r--r--core/java/android/hardware/camera2/CameraMetadata.java35
-rwxr-xr-xcore/java/android/os/Build.java5
-rw-r--r--core/java/android/provider/Settings.java9
-rw-r--r--core/java/android/service/dreams/DreamActivity.java10
-rw-r--r--core/java/android/service/dreams/DreamOverlayService.java64
-rw-r--r--core/java/android/service/dreams/DreamService.java4
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java2
-rw-r--r--core/java/android/service/quickaccesswallet/OWNERS4
-rw-r--r--core/java/android/service/quickaccesswallet/WalletCard.java51
-rw-r--r--core/java/android/service/quicksettings/TileService.java2
-rw-r--r--core/java/android/view/View.java12
-rw-r--r--core/java/android/view/ViewRootImpl.java88
-rw-r--r--core/java/android/view/Window.java5
-rw-r--r--core/java/android/view/WindowManager.java36
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java35
-rw-r--r--core/java/com/android/internal/app/procstats/ProcessState.java70
-rw-r--r--core/java/com/android/internal/app/procstats/ProcessStats.java76
-rw-r--r--core/java/com/android/internal/app/procstats/StatsEventOutput.java98
-rw-r--r--core/java/com/android/internal/jank/InteractionJankMonitor.java9
-rw-r--r--core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java52
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java31
-rw-r--r--core/java/com/android/internal/protolog/BaseProtoLogImpl.java13
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogImpl.java12
-rw-r--r--core/java/com/android/internal/util/LatencyTracker.java37
-rw-r--r--core/proto/android/providers/settings/secure.proto2
-rw-r--r--core/res/AndroidManifest.xml6
-rw-r--r--core/res/res/layout/transient_notification.xml2
-rw-r--r--core/res/res/layout/transient_notification_with_icon.xml2
-rw-r--r--core/res/res/values-af/strings.xml3
-rw-r--r--core/res/res/values-am/strings.xml3
-rw-r--r--core/res/res/values-ar/strings.xml3
-rw-r--r--core/res/res/values-as/strings.xml3
-rw-r--r--core/res/res/values-az/strings.xml3
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml3
-rw-r--r--core/res/res/values-be/strings.xml3
-rw-r--r--core/res/res/values-bg/strings.xml3
-rw-r--r--core/res/res/values-bn/strings.xml3
-rw-r--r--core/res/res/values-bs/strings.xml4
-rw-r--r--core/res/res/values-ca/strings.xml13
-rw-r--r--core/res/res/values-cs/strings.xml3
-rw-r--r--core/res/res/values-da/strings.xml3
-rw-r--r--core/res/res/values-de/strings.xml5
-rw-r--r--core/res/res/values-el/strings.xml3
-rw-r--r--core/res/res/values-es-rUS/strings.xml7
-rw-r--r--core/res/res/values-es/strings.xml9
-rw-r--r--core/res/res/values-et/strings.xml3
-rw-r--r--core/res/res/values-eu/strings.xml7
-rw-r--r--core/res/res/values-fa/strings.xml13
-rw-r--r--core/res/res/values-fi/strings.xml3
-rw-r--r--core/res/res/values-fr-rCA/strings.xml3
-rw-r--r--core/res/res/values-fr/strings.xml3
-rw-r--r--core/res/res/values-gl/strings.xml7
-rw-r--r--core/res/res/values-gu/strings.xml3
-rw-r--r--core/res/res/values-hi/strings.xml3
-rw-r--r--core/res/res/values-hu/strings.xml3
-rw-r--r--core/res/res/values-hy/strings.xml5
-rw-r--r--core/res/res/values-in/strings.xml3
-rw-r--r--core/res/res/values-is/strings.xml3
-rw-r--r--core/res/res/values-it/strings.xml11
-rw-r--r--core/res/res/values-iw/strings.xml3
-rw-r--r--core/res/res/values-ja/strings.xml3
-rw-r--r--core/res/res/values-ka/strings.xml3
-rw-r--r--core/res/res/values-kk/strings.xml3
-rw-r--r--core/res/res/values-km/strings.xml3
-rw-r--r--core/res/res/values-kn/strings.xml3
-rw-r--r--core/res/res/values-ko/strings.xml7
-rw-r--r--core/res/res/values-ky/strings.xml5
-rw-r--r--core/res/res/values-lo/strings.xml3
-rw-r--r--core/res/res/values-lt/strings.xml3
-rw-r--r--core/res/res/values-lv/strings.xml3
-rw-r--r--core/res/res/values-mcc334-mnc020-th/strings.xml2
-rw-r--r--core/res/res/values-mk/strings.xml3
-rw-r--r--core/res/res/values-ml/strings.xml3
-rw-r--r--core/res/res/values-mn/strings.xml3
-rw-r--r--core/res/res/values-mr/strings.xml3
-rw-r--r--core/res/res/values-ms/strings.xml3
-rw-r--r--core/res/res/values-my/strings.xml3
-rw-r--r--core/res/res/values-nb/strings.xml3
-rw-r--r--core/res/res/values-ne/strings.xml3
-rw-r--r--core/res/res/values-nl/strings.xml3
-rw-r--r--core/res/res/values-or/strings.xml5
-rw-r--r--core/res/res/values-pa/strings.xml3
-rw-r--r--core/res/res/values-pl/strings.xml3
-rw-r--r--core/res/res/values-pt-rBR/strings.xml3
-rw-r--r--core/res/res/values-pt-rPT/strings.xml28
-rw-r--r--core/res/res/values-pt/strings.xml3
-rw-r--r--core/res/res/values-ro/strings.xml3
-rw-r--r--core/res/res/values-ru/strings.xml11
-rw-r--r--core/res/res/values-si/strings.xml3
-rw-r--r--core/res/res/values-sk/strings.xml5
-rw-r--r--core/res/res/values-sl/strings.xml3
-rw-r--r--core/res/res/values-sq/strings.xml3
-rw-r--r--core/res/res/values-sr/strings.xml3
-rw-r--r--core/res/res/values-sv/strings.xml5
-rw-r--r--core/res/res/values-sw/strings.xml3
-rw-r--r--core/res/res/values-ta/strings.xml3
-rw-r--r--core/res/res/values-te/strings.xml3
-rw-r--r--core/res/res/values-th/strings.xml3
-rw-r--r--core/res/res/values-tl/strings.xml3
-rw-r--r--core/res/res/values-tr/strings.xml3
-rw-r--r--core/res/res/values-uk/strings.xml3
-rw-r--r--core/res/res/values-ur/strings.xml7
-rw-r--r--core/res/res/values-uz/strings.xml7
-rw-r--r--core/res/res/values-vi/strings.xml3
-rw-r--r--core/res/res/values-zh-rCN/strings.xml3
-rw-r--r--core/res/res/values-zh-rHK/strings.xml3
-rw-r--r--core/res/res/values-zh-rTW/strings.xml3
-rw-r--r--core/res/res/values-zu/strings.xml3
-rw-r--r--core/res/res/values/config.xml7
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java159
-rw-r--r--data/etc/privapp-permissions-platform.xml6
-rw-r--r--data/etc/services.core.protolog.json6
-rw-r--r--libs/WindowManager/Shell/Android.bp1
-rw-r--r--libs/WindowManager/Shell/OWNERS2
-rw-r--r--libs/WindowManager/Shell/res/color-night/taskbar_background.xml (renamed from libs/WindowManager/Shell/res/color/split_divider_background.xml)3
-rw-r--r--libs/WindowManager/Shell/res/color/taskbar_background.xml2
-rw-r--r--libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml2
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml21
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml31
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml32
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml23
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml34
-rw-r--r--libs/WindowManager/Shell/res/layout/compat_mode_hint.xml6
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml25
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml2
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml12
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-af/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-am/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-ar/strings.xml27
-rw-r--r--libs/WindowManager/Shell/res/values-as/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-az/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-be/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-bg/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-bn/strings.xml27
-rw-r--r--libs/WindowManager/Shell/res/values-bs/strings.xml8
-rw-r--r--libs/WindowManager/Shell/res/values-ca/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-cs/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-da/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-de/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-el/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-es-rUS/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-es/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-et/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-eu/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-fa/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-fi/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-fr-rCA/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-fr/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-gl/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-gu/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-hi/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-hu/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-hy/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-in/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-is/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-it/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-iw/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-ja/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-ka/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-kk/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-km/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-kn/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-ko/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-ky/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-lo/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-lt/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-lv/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-mk/strings.xml27
-rw-r--r--libs/WindowManager/Shell/res/values-ml/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-mn/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-mr/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-ms/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-my/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-nb/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-ne/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-night/colors.xml1
-rw-r--r--libs/WindowManager/Shell/res/values-nl/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-or/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-pa/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-pl/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-pt-rBR/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-pt/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-ro/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-ru/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-si/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-sk/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-sl/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-sq/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-sr/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-sv/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-sw/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-ta/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-te/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-th/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-tl/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-tr/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-uk/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-ur/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-uz/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-vi/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rCN/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rHK/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rTW/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-zu/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values/colors.xml6
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml51
-rw-r--r--libs/WindowManager/Shell/res/values/styles.xml37
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java163
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java112
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java150
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/TabletopModeController.java208
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java29
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java27
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java35
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java46
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java44
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java271
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java22
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java33
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java127
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java29
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java17
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java64
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java14
-rw-r--r--libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml1
-rw-r--r--libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DevicePostureControllerTest.java109
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TabletopModeControllerTest.java270
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java30
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java8
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java3
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt339
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java22
-rw-r--r--libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java9
-rw-r--r--libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.java111
-rw-r--r--libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java39
-rw-r--r--libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.java113
-rw-r--r--media/java/android/media/projection/OWNERS2
-rw-r--r--media/tests/MediaFrameworkTest/AndroidManifest.xml1
-rw-r--r--packages/AppPredictionLib/Android.bp2
-rw-r--r--packages/CompanionDeviceManager/res/values-vi/strings.xml2
-rw-r--r--packages/SettingsLib/Android.bp2
-rw-r--r--packages/SettingsLib/DeviceStateRotationLock/OWNERS1
-rw-r--r--packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java46
-rw-r--r--packages/SettingsLib/res/values-af/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-af/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-am/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ar/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-as/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-az/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-be/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-bg/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-bn/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-bs/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ca/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-cs/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-da/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-de/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-el/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-es-rUS/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-es/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-et/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-eu/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fa/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-fi/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-fr/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-gl/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-gu/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-hi/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-hu/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-hy/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-in/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-is/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-it/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-iw/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ja/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ka/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-kk/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-km/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-kn/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ko/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ky/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-lo/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-lt/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-lv/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-mk/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ml/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-mn/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-mr/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ms/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-my/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-nb/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ne/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ne/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-nl/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-or/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-pa/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-pl/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-pt/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ro/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ru/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-si/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sk/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sk/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sl/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sq/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sr/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sv/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sw/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ta/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-te/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-th/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-tl/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-tr/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-uk/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ur/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-uz/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-vi/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-zh-rHK/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-zu/arrays.xml14
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java3
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java41
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java25
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java25
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java3
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java1
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java3
-rw-r--r--packages/SystemUI/TEST_MAPPING19
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt8
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt26
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt5
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt4
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt5
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt6
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt149
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt120
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt15
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt80
-rw-r--r--packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt94
-rw-r--r--packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt127
-rw-r--r--packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt4
-rw-r--r--packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt27
-rw-r--r--packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt313
-rw-r--r--packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt332
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt18
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt4
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt4
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt34
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt2
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt4
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt2
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt4
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt7
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt16
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt20
-rw-r--r--packages/SystemUI/ktfmt_includes.txt123
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt18
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/Weather.kt85
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/WeatherData.kt107
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt33
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt1
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java6
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt2
-rw-r--r--packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.pngbin2602 -> 0 bytes
-rw-r--r--packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.pngbin5201 -> 0 bytes
-rw-r--r--packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png (renamed from packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png)bin4083 -> 4083 bytes
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml4
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml341
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml301
-rw-r--r--packages/SystemUI/res-keyguard/values-eu/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-hi/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ja/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-kk/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-land/dimens.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values/dimens.xml6
-rw-r--r--packages/SystemUI/res-product/values-af/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-am/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ar/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-as/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-az/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-b+sr+Latn/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-be/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-bg/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-bn/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-bs/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ca/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-cs/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-da/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-de/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-el/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-en-rAU/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-en-rCA/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-en-rGB/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-en-rIN/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-en-rXC/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-es-rUS/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-es/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-et/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-eu/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-fa/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-fi/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-fr-rCA/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-fr/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-gl/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-gu/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-hi/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-hr/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-hu/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-hy/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-in/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-is/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-it/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-iw/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ja/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ka/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-kk/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-km/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-kn/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ko/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ky/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-lo/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-lt/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-lv/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-mk/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ml/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-mn/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-mr/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ms/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-my/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-nb/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ne/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-nl/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-or/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-pa/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-pl/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-pt-rBR/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-pt-rPT/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-pt/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ro/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ru/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-si/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-sk/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-sl/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-sq/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-sr/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-sv/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-sw/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ta/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-te/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-th/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-tl/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-tr/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-uk/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-ur/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-uz/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-vi/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-zh-rCN/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-zh-rHK/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-zh-rTW/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-zu/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values/strings.xml9
-rw-r--r--packages/SystemUI/res/drawable/chipbar_background.xml (renamed from packages/SystemUI/res/drawable/media_ttt_chip_background.xml)2
-rw-r--r--packages/SystemUI/res/drawable/chipbar_end_button_background.xml (renamed from packages/SystemUI/res/drawable/media_ttt_undo_background.xml)2
-rw-r--r--packages/SystemUI/res/drawable/controls_panel_background.xml2
-rw-r--r--packages/SystemUI/res/drawable/dream_overlay_bottom_affordance_bg.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_keyboard_backlight.xml12
-rw-r--r--packages/SystemUI/res/drawable/qs_footer_edit_circle.xml36
-rw-r--r--packages/SystemUI/res/drawable/qs_media_rec_scrim.xml (renamed from libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml)13
-rw-r--r--packages/SystemUI/res/drawable/statusbar_chip_bg.xml23
-rw-r--r--packages/SystemUI/res/drawable/statusbar_privacy_chip_bg.xml (renamed from packages/SystemUI/res/drawable/privacy_chip_bg.xml)0
-rw-r--r--packages/SystemUI/res/layout/battery_status_chip.xml43
-rw-r--r--packages/SystemUI/res/layout/chipbar.xml47
-rw-r--r--packages/SystemUI/res/layout/combined_qs_header.xml11
-rw-r--r--packages/SystemUI/res/layout/controls_fullscreen.xml12
-rw-r--r--packages/SystemUI/res/layout/controls_with_favorites.xml140
-rw-r--r--packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml9
-rw-r--r--packages/SystemUI/res/layout/large_screen_shade_header.xml100
-rw-r--r--packages/SystemUI/res/layout/media_recommendation_view.xml3
-rw-r--r--packages/SystemUI/res/layout/ongoing_privacy_chip.xml14
-rw-r--r--packages/SystemUI/res/layout/qs_footer_impl.xml2
-rw-r--r--packages/SystemUI/res/layout/quick_qs_status_icons.xml111
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml32
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml75
-rw-r--r--packages/SystemUI/res/raw/biometricprompt_rear_landscape_base.json1
-rw-r--r--packages/SystemUI/res/raw/biometricprompt_rear_portrait_base.json1
-rw-r--r--packages/SystemUI/res/raw/biometricprompt_rear_portrait_reverse_base.json1
-rw-r--r--packages/SystemUI/res/values-af/strings.xml43
-rw-r--r--packages/SystemUI/res/values-af/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-am/strings.xml52
-rw-r--r--packages/SystemUI/res/values-am/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml55
-rw-r--r--packages/SystemUI/res/values-ar/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-as/strings.xml49
-rw-r--r--packages/SystemUI/res/values-as/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-az/strings.xml49
-rw-r--r--packages/SystemUI/res/values-az/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml45
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-be/strings.xml49
-rw-r--r--packages/SystemUI/res/values-be/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml49
-rw-r--r--packages/SystemUI/res/values-bg/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml43
-rw-r--r--packages/SystemUI/res/values-bn/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml35
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml53
-rw-r--r--packages/SystemUI/res/values-ca/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml43
-rw-r--r--packages/SystemUI/res/values-cs/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-da/strings.xml49
-rw-r--r--packages/SystemUI/res/values-da/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-de/strings.xml43
-rw-r--r--packages/SystemUI/res/values-de/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-el/strings.xml49
-rw-r--r--packages/SystemUI/res/values-el/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml25
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml23
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml25
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml25
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml23
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml51
-rw-r--r--packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-es/strings.xml57
-rw-r--r--packages/SystemUI/res/values-es/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-et/strings.xml47
-rw-r--r--packages/SystemUI/res/values-et/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml43
-rw-r--r--packages/SystemUI/res/values-eu/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml49
-rw-r--r--packages/SystemUI/res/values-fa/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml53
-rw-r--r--packages/SystemUI/res/values-fi/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml49
-rw-r--r--packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml53
-rw-r--r--packages/SystemUI/res/values-fr/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml51
-rw-r--r--packages/SystemUI/res/values-gl/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml49
-rw-r--r--packages/SystemUI/res/values-gu/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml43
-rw-r--r--packages/SystemUI/res/values-hi/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml29
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml49
-rw-r--r--packages/SystemUI/res/values-hu/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml45
-rw-r--r--packages/SystemUI/res/values-hy/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-in/strings.xml49
-rw-r--r--packages/SystemUI/res/values-in/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-is/strings.xml53
-rw-r--r--packages/SystemUI/res/values-is/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-it/strings.xml55
-rw-r--r--packages/SystemUI/res/values-it/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml45
-rw-r--r--packages/SystemUI/res/values-iw/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml43
-rw-r--r--packages/SystemUI/res/values-ja/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml43
-rw-r--r--packages/SystemUI/res/values-ka/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml49
-rw-r--r--packages/SystemUI/res/values-kk/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-km/strings.xml49
-rw-r--r--packages/SystemUI/res/values-km/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml43
-rw-r--r--packages/SystemUI/res/values-kn/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml51
-rw-r--r--packages/SystemUI/res/values-ko/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml49
-rw-r--r--packages/SystemUI/res/values-ky/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-land/dimens.xml8
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml43
-rw-r--r--packages/SystemUI/res/values-lo/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml43
-rw-r--r--packages/SystemUI/res/values-lt/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml53
-rw-r--r--packages/SystemUI/res/values-lv/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml49
-rw-r--r--packages/SystemUI/res/values-mk/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml43
-rw-r--r--packages/SystemUI/res/values-ml/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml49
-rw-r--r--packages/SystemUI/res/values-mn/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml51
-rw-r--r--packages/SystemUI/res/values-mr/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml43
-rw-r--r--packages/SystemUI/res/values-ms/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-my/strings.xml49
-rw-r--r--packages/SystemUI/res/values-my/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml49
-rw-r--r--packages/SystemUI/res/values-nb/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml45
-rw-r--r--packages/SystemUI/res/values-ne/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml43
-rw-r--r--packages/SystemUI/res/values-nl/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-or/strings.xml47
-rw-r--r--packages/SystemUI/res/values-or/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml45
-rw-r--r--packages/SystemUI/res/values-pa/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml43
-rw-r--r--packages/SystemUI/res/values-pl/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml51
-rw-r--r--packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml29
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml51
-rw-r--r--packages/SystemUI/res/values-pt/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml43
-rw-r--r--packages/SystemUI/res/values-ro/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml49
-rw-r--r--packages/SystemUI/res/values-ru/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-si/strings.xml49
-rw-r--r--packages/SystemUI/res/values-si/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml45
-rw-r--r--packages/SystemUI/res/values-sk/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml47
-rw-r--r--packages/SystemUI/res/values-sl/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml43
-rw-r--r--packages/SystemUI/res/values-sq/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml45
-rw-r--r--packages/SystemUI/res/values-sr/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml49
-rw-r--r--packages/SystemUI/res/values-sv/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml49
-rw-r--r--packages/SystemUI/res/values-sw/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-sw600dp/dimens.xml4
-rw-r--r--packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml4
-rw-r--r--packages/SystemUI/res/values-sw720dp-land/dimens.xml2
-rw-r--r--packages/SystemUI/res/values-sw720dp-port/dimens.xml2
-rw-r--r--packages/SystemUI/res/values-sw720dp/dimens.xml3
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml49
-rw-r--r--packages/SystemUI/res/values-ta/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-te/strings.xml45
-rw-r--r--packages/SystemUI/res/values-te/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-th/strings.xml43
-rw-r--r--packages/SystemUI/res/values-th/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml49
-rw-r--r--packages/SystemUI/res/values-tl/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml49
-rw-r--r--packages/SystemUI/res/values-tr/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml51
-rw-r--r--packages/SystemUI/res/values-uk/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml57
-rw-r--r--packages/SystemUI/res/values-ur/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml51
-rw-r--r--packages/SystemUI/res/values-uz/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml49
-rw-r--r--packages/SystemUI/res/values-vi/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml51
-rw-r--r--packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml51
-rw-r--r--packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml43
-rw-r--r--packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml43
-rw-r--r--packages/SystemUI/res/values-zu/tiles_states_strings.xml8
-rw-r--r--packages/SystemUI/res/values/colors.xml6
-rw-r--r--packages/SystemUI/res/values/config.xml2
-rw-r--r--packages/SystemUI/res/values/dimens.xml57
-rw-r--r--packages/SystemUI/res/values/flags.xml3
-rw-r--r--packages/SystemUI/res/values/strings.xml16
-rw-r--r--packages/SystemUI/screenshot/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt27
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt33
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java45
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt16
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java115
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java15
-rw-r--r--packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt10
-rw-r--r--packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt18
-rw-r--r--packages/SystemUI/src/com/android/keyguard/ClockEventController.kt46
-rw-r--r--packages/SystemUI/src/com/android/keyguard/EmergencyButton.java9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java114
-rw-r--r--packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java27
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java10
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java48
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java78
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java174
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java19
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java21
-rw-r--r--packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/NumPadKey.java3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt31
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt63
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt657
-rw-r--r--packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt41
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt48
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java94
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt43
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt50
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt39
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepository.kt64
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.kt95
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt97
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt92
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java107
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/ConditionalRestarter.kt103
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugRestarter.kt70
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseRestarter.kt101
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt96
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/PluggedInCondition.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/ScreenIdleCondition.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt41
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/KeyboardBacklightDialogCoordinator.kt66
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt276
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogContentViewModel.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModel.kt72
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt100
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shared/model/BacklightModel.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java76
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt27
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt58
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt59
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt80
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt50
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt42
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt119
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt41
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ScrimAlpha.kt (renamed from packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBouncerModel.kt)13
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt96
-rw-r--r--packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/DeviceStateAutoRotationLog.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt63
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt126
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java111
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java181
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt39
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt71
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java (renamed from packages/SystemUI/src/com/android/systemui/process/condition/UserProcessCondition.java)15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSHost.java71
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java462
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java161
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java255
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java89
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt (renamed from packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt)292
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt58
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenPortraitShadeInterpolator.kt46
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolator.kt36
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImpl.kt74
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeInterpolator.kt63
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt167
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt71
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt116
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt322
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt425
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt314
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt114
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java56
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java86
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java94
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java127
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt86
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileViewLog.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/VerboseMobileViewLog.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt (renamed from packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt)24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt176
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt57
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt231
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt72
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt83
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt151
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt235
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt68
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt118
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt76
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileView.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewBinding.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt140
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt43
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt112
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt20
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java198
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java46
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java323
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt216
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt208
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt156
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java116
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt38
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt89
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt36
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/panels/FakeSelectedComponentRepository.kt42
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/panels/SelectedComponentRepositoryTest.kt163
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt108
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt89
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt165
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt66
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java76
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java42
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java38
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt140
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseRestarterTest.kt146
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt76
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt (renamed from packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugRestarterTest.kt)39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt73
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModelTest.kt102
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt191
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt52
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt80
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt255
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt127
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt83
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt180
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt88
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt227
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt55
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt328
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt71
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt89
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt74
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt51
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt87
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java76
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/process/condition/UserProcessConditionTest.java)29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java66
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java129
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt157
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt41
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java70
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt66
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt319
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java752
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java784
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt179
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt149
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java350
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt (renamed from packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt)597
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImplTest.kt144
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/transition/LinearLargeScreenShadeInterpolator.kt25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt130
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt112
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt35
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt35
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt470
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt231
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt111
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt163
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java85
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt300
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java34
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java149
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt62
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java66
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java48
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java195
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java103
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt44
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java46
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLoggerTest.kt (renamed from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt)7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt106
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt42
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt63
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt106
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt213
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt450
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt341
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.kt17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt173
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt100
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt80
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt45
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt121
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt124
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java14
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt1
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeKeyboardRepository.kt41
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt31
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt28
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt3
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt17
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt86
-rw-r--r--packages/SystemUI/unfold/Android.bp1
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt9
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt12
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt12
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt26
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt64
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt13
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/RotationChangeProvider.kt48
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt3
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt1
-rw-r--r--packages/VpnDialogs/res/values-fr/strings.xml2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java6
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java45
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java5
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java16
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java51
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java4
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java72
-rw-r--r--services/core/java/com/android/server/display/AutomaticBrightnessController.java8
-rw-r--r--services/core/java/com/android/server/display/BrightnessMappingStrategy.java18
-rw-r--r--services/core/java/com/android/server/display/BrightnessSetting.java17
-rw-r--r--services/core/java/com/android/server/display/DisplayDevice.java7
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java10
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java124
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplay.java2
-rw-r--r--services/core/java/com/android/server/display/PersistentDataStore.java27
-rw-r--r--services/core/java/com/android/server/dreams/DreamController.java7
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java116
-rw-r--r--services/core/java/com/android/server/media/MediaSessionStack.java14
-rw-r--r--services/core/java/com/android/server/media/projection/OWNERS3
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java101
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java99
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java27
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java16
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java6
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java161
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java14
-rw-r--r--services/core/java/com/android/server/wm/ActivityClientController.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java243
-rw-r--r--services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java35
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java15
-rw-r--r--services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java7
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java90
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java11
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java69
-rw-r--r--services/core/java/com/android/server/wm/EventLogTags.logtags10
-rw-r--r--services/core/java/com/android/server/wm/KeyguardController.java13
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfiguration.java28
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java43
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java4
-rw-r--r--services/core/java/com/android/server/wm/LetterboxUiController.java56
-rw-r--r--services/core/java/com/android/server/wm/RemoteAnimationController.java14
-rw-r--r--services/core/java/com/android/server/wm/Task.java8
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java27
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java2
-rw-r--r--services/people/java/com/android/server/people/data/ContactsQueryHelper.java2
-rw-r--r--services/people/java/com/android/server/people/data/DataManager.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java27
-rw-r--r--services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java64
-rw-r--r--services/tests/servicestests/src/com/android/server/dreams/OWNERS1
-rw-r--r--services/tests/servicestests/src/com/android/server/media/projection/OWNERS1
-rw-r--r--services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java28
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java178
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java163
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java21
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java199
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java31
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java25
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java38
-rw-r--r--telecomm/java/android/telecom/PhoneAccount.java19
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt16
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt16
-rw-r--r--tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java2
-rw-r--r--tools/aapt2/SdkConstants.cpp2
1375 files changed, 30841 insertions, 14968 deletions
diff --git a/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java b/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
index 3b14be7327f7..24727c5f2448 100644
--- a/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
+++ b/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
@@ -107,7 +107,7 @@ public class DumpCommand extends Command {
DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
int rotation = display.getRotation();
Point size = new Point();
- display.getSize(size);
+ display.getRealSize(size);
AccessibilityNodeInfoDumper.dumpWindowToFile(info, dumpFile, rotation, size.x,
size.y);
}
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
index ab198b319e27..488292d68620 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
@@ -139,7 +139,7 @@ public class AccessibilityNodeInfoDumper {
serializer.attribute("", "id", Integer.toString(displayId));
int rotation = display.getRotation();
Point size = new Point();
- display.getSize(size);
+ display.getRealSize(size);
for (int i = 0, n = windows.size(); i < n; ++i) {
dumpWindowRec(windows.get(i), serializer, i, size.x, size.y, rotation);
}
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
index 6fd2bf250e2c..1bcd343e5668 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
@@ -767,7 +767,7 @@ public class UiDevice {
if(root != null) {
Display display = getAutomatorBridge().getDefaultDisplay();
Point size = new Point();
- display.getSize(size);
+ display.getRealSize(size);
AccessibilityNodeInfoDumper.dumpWindowToFile(root,
new File(new File(Environment.getDataDirectory(), "local/tmp"), fileName),
display.getRotation(), size.x, size.y);
diff --git a/core/api/current.txt b/core/api/current.txt
index c451049cf591..487e57d114c9 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -30978,7 +30978,6 @@ package android.os {
field public static final int S = 31; // 0x1f
field public static final int S_V2 = 32; // 0x20
field public static final int TIRAMISU = 33; // 0x21
- field public static final int UPSIDE_DOWN_CAKE = 10000; // 0x2710
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index c0e89d2c4a05..14bf5320a438 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -797,6 +797,7 @@ package android.content.pm {
field public static final long OVERRIDE_MIN_ASPECT_RATIO_MEDIUM = 180326845L; // 0xabf91bdL
field public static final float OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE = 1.5f;
field public static final long OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY = 203647190L; // 0xc2368d6L
+ field public static final long OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS = 237531167L; // 0xe28701fL
field public static final int RESIZE_MODE_RESIZEABLE = 2; // 0x2
}
@@ -2917,7 +2918,9 @@ package android.view {
}
@UiThread public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
+ method public void getBoundsOnScreen(@NonNull android.graphics.Rect, boolean);
method public android.view.View getTooltipView();
+ method public void getWindowDisplayFrame(@NonNull android.graphics.Rect);
method public boolean isAutofilled();
method public static boolean isDefaultFocusHighlightEnabled();
method public boolean isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index c17fbf19516b..dd955406e690 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -2523,6 +2523,10 @@ public abstract class AccessibilityService extends Service {
IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (mInfo != null && connection != null) {
+ if (!mInfo.isWithinParcelableSize()) {
+ throw new IllegalStateException(
+ "Cannot update service info: size is larger than safe parcelable limits.");
+ }
try {
connection.setServiceInfo(mInfo);
mInfo = null;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 530de0f3af6b..0cbcdb5a2b62 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -40,6 +40,7 @@ import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
+import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
@@ -1128,6 +1129,15 @@ public class AccessibilityServiceInfo implements Parcelable {
return 0;
}
+ /** @hide */
+ public final boolean isWithinParcelableSize() {
+ final Parcel parcel = Parcel.obtain();
+ writeToParcel(parcel, 0);
+ final boolean result = parcel.dataSize() <= IBinder.MAX_IPC_SIZE;
+ parcel.recycle();
+ return result;
+ }
+
public void writeToParcel(Parcel parcel, int flagz) {
parcel.writeInt(eventTypes);
parcel.writeStringArray(packageNames);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 449729e18376..48df9e66be70 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3933,6 +3933,9 @@ public class ActivityManager {
* processes to reclaim memory; the system will take care of restarting
* these processes in the future as needed.
*
+ * <p class="note">Third party applications can only use this API to kill their own processes.
+ * </p>
+ *
* @param packageName The name of the package whose processes are to
* be killed.
*/
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0fd80c5698a9..7f48e39a9a79 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6965,8 +6965,10 @@ public class Notification implements Parcelable
/**
* Returns whether an app can colorize due to the android.permission.USE_COLORIZED_NOTIFICATIONS
* permission. The permission is checked when a notification is enqueued.
+ *
+ * @hide
*/
- private boolean hasColorizedPermission() {
+ public boolean hasColorizedPermission() {
return (flags & Notification.FLAG_CAN_COLORIZE) != 0;
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index f6d27ad08b00..37a90de8d600 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -317,7 +317,10 @@ public class NotificationManager {
/**
* Intent that is broadcast when the state of {@link #getEffectsSuppressor()} changes.
- * This broadcast is only sent to registered receivers.
+ *
+ * <p>This broadcast is only sent to registered receivers and (starting from
+ * {@link Build.VERSION_CODES#Q}) receivers in packages that have been granted Do Not
+ * Disturb access (see {@link #isNotificationPolicyAccessGranted()}).
*
* @hide
*/
@@ -337,7 +340,10 @@ public class NotificationManager {
/**
* Intent that is broadcast when the state of getNotificationPolicy() changes.
- * This broadcast is only sent to registered receivers.
+ *
+ * <p>This broadcast is only sent to registered receivers and (starting from
+ * {@link Build.VERSION_CODES#Q}) receivers in packages that have been granted Do Not
+ * Disturb access (see {@link #isNotificationPolicyAccessGranted()}).
*/
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_NOTIFICATION_POLICY_CHANGED
@@ -345,7 +351,10 @@ public class NotificationManager {
/**
* Intent that is broadcast when the state of getCurrentInterruptionFilter() changes.
- * This broadcast is only sent to registered receivers.
+ *
+ * <p>This broadcast is only sent to registered receivers and (starting from
+ * {@link Build.VERSION_CODES#Q}) receivers in packages that have been granted Do Not
+ * Disturb access (see {@link #isNotificationPolicyAccessGranted()}).
*/
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_INTERRUPTION_FILTER_CHANGED
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 3bf3067f8410..8ee23aa8e67b 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -444,6 +444,7 @@ public class TaskInfo {
&& Objects.equals(shouldDockBigOverlays, that.shouldDockBigOverlays)
&& Objects.equals(displayCutoutInsets, that.displayCutoutInsets)
&& getWindowingMode() == that.getWindowingMode()
+ && configuration.uiMode == that.configuration.uiMode
&& Objects.equals(taskDescription, that.taskDescription)
&& isFocused == that.isFocused
&& isVisible == that.isVisible
@@ -472,6 +473,7 @@ public class TaskInfo {
.equals(that.configuration.windowConfiguration.getBounds()))
&& (!hasCompatUI() || configuration.getLayoutDirection()
== that.configuration.getLayoutDirection())
+ && (!hasCompatUI() || configuration.uiMode == that.configuration.uiMode)
&& (!hasCompatUI() || isVisible == that.isVisible);
}
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index bbe99f59fc21..226278cbe44d 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1104,6 +1104,34 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
264301586L; // buganizer id
/**
+ * This change id forces the packages it is applied to sandbox {@link android.view.View} API to
+ * an activity bounds for:
+ *
+ * <p>{@link android.view.View#getLocationOnScreen},
+ * {@link android.view.View#getWindowVisibleDisplayFrame},
+ * {@link android.view.View}#getWindowDisplayFrame,
+ * {@link android.view.View}#getBoundsOnScreen.
+ *
+ * <p>For {@link android.view.View#getWindowVisibleDisplayFrame} and
+ * {@link android.view.View}#getWindowDisplayFrame this sandboxing is happening indirectly
+ * through
+ * {@link android.view.ViewRootImpl}#getWindowVisibleDisplayFrame,
+ * {@link android.view.ViewRootImpl}#getDisplayFrame respectively.
+ *
+ * <p>Some applications assume that they occupy the whole screen and therefore use the display
+ * coordinates in their calculations as if an activity is positioned in the top-left corner of
+ * the screen, with left coordinate equal to 0. This may not be the case of applications in
+ * multi-window and in letterbox modes. This can lead to shifted or out of bounds UI elements in
+ * case the activity is Letterboxed or is in multi-window mode.
+ * @hide
+ */
+ @ChangeId
+ @Overridable
+ @Disabled
+ @TestApi
+ public static final long OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS = 237531167L; // buganizer id
+
+ /**
* This change id is the gatekeeper for all treatments that force a given min aspect ratio.
* Enabling this change will allow the following min aspect ratio treatments to be applied:
* OVERRIDE_MIN_ASPECT_RATIO_MEDIUM
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 14d0a563f2ca..9d624b6c0ed8 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -3517,7 +3517,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* <p>An array of mandatory stream combinations which are applicable when device support the
* 10-bit output capability
* {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT }
- * This is an app-readable conversion of the maximum resolution mandatory stream combination
+ * This is an app-readable conversion of the 10 bit output mandatory stream combination
* {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
* <p>The array of
* {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
@@ -3542,8 +3542,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
/**
* <p>An array of mandatory stream combinations which are applicable when device lists
* {@code PREVIEW_STABILIZATION} in {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES android.control.availableVideoStabilizationModes}.
- * This is an app-readable conversion of the maximum resolution mandatory stream combination
- * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
+ * This is an app-readable conversion of the preview stabilization mandatory stream
+ * combination {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
* <p>The array of
* {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
* generated according to the documented
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 32cf0a755de9..56592ab43143 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -1189,8 +1189,8 @@ public final class CameraManager {
PackageManager packageManager = context.getPackageManager();
try {
- return packageManager.getProperty(context.getOpPackageName(),
- PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT).getBoolean();
+ return packageManager.getProperty(PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT,
+ context.getOpPackageName()).getBoolean();
} catch (PackageManager.NameNotFoundException e) {
// No such property
}
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index c67a560b5885..7055c9c6aa4d 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1000,24 +1000,25 @@ public abstract class CameraMetadata<TKey> {
* camera's crop region is set to maximum size, the FOV of the physical streams for the
* ultrawide lens will be the same as the logical stream, by making the crop region
* smaller than its active array size to compensate for the smaller focal length.</p>
- * <p>There are two ways for the application to capture RAW images from a logical camera
- * with RAW capability:</p>
+ * <p>For a logical camera, typically the underlying physical cameras have different RAW
+ * capabilities (such as resolution or CFA pattern). There are two ways for the
+ * application to capture RAW images from the logical camera:</p>
* <ul>
- * <li>Because the underlying physical cameras may have different RAW capabilities (such
- * as resolution or CFA pattern), to maintain backward compatibility, when a RAW stream
- * is configured, the camera device makes sure the default active physical camera remains
- * active and does not switch to other physical cameras. (One exception is that, if the
- * logical camera consists of identical image sensors and advertises multiple focalLength
- * due to different lenses, the camera device may generate RAW images from different
- * physical cameras based on the focalLength being set by the application.) This
- * backward-compatible approach usually results in loss of optical zoom, to telephoto
- * lens or to ultrawide lens.</li>
- * <li>Alternatively, to take advantage of the full zoomRatio range of the logical camera,
- * the application should use {@link android.hardware.camera2.MultiResolutionImageReader }
- * to capture RAW images from the currently active physical camera. Because different
- * physical camera may have different RAW characteristics, the application needs to use
- * the characteristics and result metadata of the active physical camera for the
- * relevant RAW metadata.</li>
+ * <li>If the logical camera has RAW capability, the application can create and use RAW
+ * streams in the same way as before. In case a RAW stream is configured, to maintain
+ * backward compatibility, the camera device makes sure the default active physical
+ * camera remains active and does not switch to other physical cameras. (One exception
+ * is that, if the logical camera consists of identical image sensors and advertises
+ * multiple focalLength due to different lenses, the camera device may generate RAW
+ * images from different physical cameras based on the focalLength being set by the
+ * application.) This backward-compatible approach usually results in loss of optical
+ * zoom, to telephoto lens or to ultrawide lens.</li>
+ * <li>Alternatively, if supported by the device,
+ * {@link android.hardware.camera2.MultiResolutionImageReader }
+ * can be used to capture RAW images from one of the underlying physical cameras (
+ * depending on current zoom level). Because different physical cameras may have
+ * different RAW characteristics, the application needs to use the characteristics
+ * and result metadata of the active physical camera for the relevant RAW metadata.</li>
* </ul>
* <p>The capture request and result metadata tags required for backward compatible camera
* functionalities will be solely based on the logical camera capability. On the other
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index dbd602f27c11..0b956f8bf9e0 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1167,11 +1167,6 @@ public class Build {
* Tiramisu.
*/
public static final int TIRAMISU = 33;
-
- /**
- * Upside Down Cake.
- */
- public static final int UPSIDE_DOWN_CAKE = CUR_DEVELOPMENT;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 10e1633b22d7..6b25c81218e8 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8001,6 +8001,15 @@ public final class Settings {
"accessibility_display_inversion_enabled";
/**
+ * Flag that specifies whether font size has been changed. The flag will
+ * be set when users change the scaled value of font size for the first time.
+ * @hide
+ */
+ @Readable
+ public static final String ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED =
+ "accessibility_font_scaling_has_been_changed";
+
+ /**
* Setting that specifies whether display color space adjustment is
* enabled.
*
diff --git a/core/java/android/service/dreams/DreamActivity.java b/core/java/android/service/dreams/DreamActivity.java
index a2fa1392b079..a3892238f1e6 100644
--- a/core/java/android/service/dreams/DreamActivity.java
+++ b/core/java/android/service/dreams/DreamActivity.java
@@ -58,11 +58,13 @@ public class DreamActivity extends Activity {
setTitle(title);
}
- final Bundle extras = getIntent().getExtras();
- mCallback = (DreamService.DreamActivityCallbacks) extras.getBinder(EXTRA_CALLBACK);
-
- if (mCallback != null) {
+ final Object callback = getIntent().getExtras().getBinder(EXTRA_CALLBACK);
+ if (callback instanceof DreamService.DreamActivityCallbacks) {
+ mCallback = (DreamService.DreamActivityCallbacks) callback;
mCallback.onActivityCreated(this);
+ } else {
+ mCallback = null;
+ finishAndRemoveTask();
}
}
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index 6e4535b7218a..5469916bea4e 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -27,6 +27,8 @@ import android.os.RemoteException;
import android.util.Log;
import android.view.WindowManager;
+import java.util.concurrent.Executor;
+
/**
* Basic implementation of for {@link IDreamOverlay} for testing.
@@ -40,6 +42,12 @@ public abstract class DreamOverlayService extends Service {
// The last client that started dreaming and hasn't ended
private OverlayClient mCurrentClient;
+ /**
+ * Executor used to run callbacks that subclasses will implement. Any calls coming over Binder
+ * from {@link OverlayClient} should perform the work they need to do on this executor.
+ */
+ private Executor mExecutor;
+
// An {@link IDreamOverlayClient} implementation that identifies itself when forwarding
// requests to the {@link DreamOverlayService}
private static class OverlayClient extends IDreamOverlayClient.Stub {
@@ -61,8 +69,6 @@ public abstract class DreamOverlayService extends Service {
mService.startDream(this, params);
}
-
-
@Override
public void wakeUp() {
mService.wakeUp(this, () -> {
@@ -97,12 +103,20 @@ public abstract class DreamOverlayService extends Service {
}
private void startDream(OverlayClient client, WindowManager.LayoutParams params) {
- endDream(mCurrentClient);
- mCurrentClient = client;
- onStartDream(params);
+ // Run on executor as this is a binder call from OverlayClient.
+ mExecutor.execute(() -> {
+ endDreamInternal(mCurrentClient);
+ mCurrentClient = client;
+ onStartDream(params);
+ });
}
private void endDream(OverlayClient client) {
+ // Run on executor as this is a binder call from OverlayClient.
+ mExecutor.execute(() -> endDreamInternal(client));
+ }
+
+ private void endDreamInternal(OverlayClient client) {
if (client == null || client != mCurrentClient) {
return;
}
@@ -112,11 +126,14 @@ public abstract class DreamOverlayService extends Service {
}
private void wakeUp(OverlayClient client, Runnable callback) {
- if (mCurrentClient != client) {
- return;
- }
+ // Run on executor as this is a binder call from OverlayClient.
+ mExecutor.execute(() -> {
+ if (mCurrentClient != client) {
+ return;
+ }
- onWakeUp(callback);
+ onWakeUp(callback);
+ });
}
private IDreamOverlay mDreamOverlay = new IDreamOverlay.Stub() {
@@ -134,6 +151,25 @@ public abstract class DreamOverlayService extends Service {
public DreamOverlayService() {
}
+ /**
+ * This constructor allows providing an executor to run callbacks on.
+ *
+ * @hide
+ */
+ public DreamOverlayService(@NonNull Executor executor) {
+ mExecutor = executor;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ if (mExecutor == null) {
+ // If no executor was provided, use the main executor. onCreate is the earliest time
+ // getMainExecutor is available.
+ mExecutor = getMainExecutor();
+ }
+ }
+
@Nullable
@Override
public final IBinder onBind(@NonNull Intent intent) {
@@ -143,6 +179,10 @@ public abstract class DreamOverlayService extends Service {
/**
* This method is overridden by implementations to handle when the dream has started and the
* window is ready to be interacted with.
+ *
+ * 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 layoutParams The {@link android.view.WindowManager.LayoutParams} associated with the
* dream window.
*/
@@ -153,6 +193,9 @@ public abstract class DreamOverlayService extends Service {
* 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.
* @hide
@@ -164,6 +207,9 @@ public abstract class DreamOverlayService extends Service {
/**
* This method is overridden by implementations to handle when the dream has ended. There may
* be earlier signals leading up to this step, such as @{@link #onWakeUp(Runnable)}.
+ *
+ * This callback will be run on the {@link Executor} provided in the constructor if provided, or
+ * on the main executor if none was provided.
*/
public void onEndDream() {
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index d79ea8929047..224307297e76 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -1409,6 +1409,10 @@ public class DreamService extends Service implements Window.Callback {
// Request the DreamOverlay be told to dream with dream's window
// parameters once the window has been attached.
mDreamStartOverlayConsumer = overlay -> {
+ if (mWindow == null) {
+ Slog.d(TAG, "mWindow is null");
+ return;
+ }
try {
overlay.startDream(mWindow.getAttributes(), mOverlayCallback,
mDreamComponent.flattenToString(),
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index e285b1c77122..9d8c963e2f8b 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -953,7 +953,7 @@ public class ZenModeConfig implements Parcelable {
private static Uri safeUri(TypedXmlPullParser parser, String att) {
final String val = parser.getAttributeValue(null, att);
- if (TextUtils.isEmpty(val)) return null;
+ if (val == null) return null;
return Uri.parse(val);
}
diff --git a/core/java/android/service/quickaccesswallet/OWNERS b/core/java/android/service/quickaccesswallet/OWNERS
new file mode 100644
index 000000000000..232ee02d3b04
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 802986
+asc@google.com
+juliacr@google.com
+steell@google.com
diff --git a/core/java/android/service/quickaccesswallet/WalletCard.java b/core/java/android/service/quickaccesswallet/WalletCard.java
index 7aacb9b4d11a..e234755b2b13 100644
--- a/core/java/android/service/quickaccesswallet/WalletCard.java
+++ b/core/java/android/service/quickaccesswallet/WalletCard.java
@@ -36,7 +36,7 @@ import java.lang.annotation.RetentionPolicy;
* card, library card, transit pass, etc. Cards are identified by a String identifier and contain a
* card type, card image, card image content description, and a {@link PendingIntent} to be used if
* the user clicks on the card. Cards may be displayed with an icon and label, though these are
- * optional. Valuable cards will also have a second image that will be displayed when the card is
+ * optional. Non-payment cards will also have a second image that will be displayed when the card is
* tapped.
*/
@@ -56,11 +56,11 @@ public final class WalletCard implements Parcelable {
public static final int CARD_TYPE_PAYMENT = 1;
/**
- * Valuable cards refer to any cards that are not used for cash-equivalent payment.
- * This includes event tickets, flights, offers, loyalty cards, gift cards and transit tickets.
+ * Non-payment cards refer to any cards that are not used for cash-equivalent payment, including
+ * event tickets, flights, offers, loyalty cards, gift cards and transit tickets.
* @hide
*/
- public static final int CARD_TYPE_VALUABLE = 2;
+ public static final int CARD_TYPE_NON_PAYMENT = 2;
private final String mCardId;
private final int mCardType;
@@ -69,7 +69,7 @@ public final class WalletCard implements Parcelable {
private final PendingIntent mPendingIntent;
private final Icon mCardIcon;
private final CharSequence mCardLabel;
- private final Icon mValuableCardSecondaryImage;
+ private final Icon mNonPaymentCardSecondaryImage;
private WalletCard(Builder builder) {
this.mCardId = builder.mCardId;
@@ -79,7 +79,7 @@ public final class WalletCard implements Parcelable {
this.mPendingIntent = builder.mPendingIntent;
this.mCardIcon = builder.mCardIcon;
this.mCardLabel = builder.mCardLabel;
- this.mValuableCardSecondaryImage = builder.mValuableCardSecondaryImage;
+ this.mNonPaymentCardSecondaryImage = builder.mNonPaymentCardSecondaryImage;
}
/**
@@ -89,7 +89,7 @@ public final class WalletCard implements Parcelable {
@IntDef(prefix = {"CARD_TYPE_"}, value = {
CARD_TYPE_UNKNOWN,
CARD_TYPE_PAYMENT,
- CARD_TYPE_VALUABLE
+ CARD_TYPE_NON_PAYMENT
})
public @interface CardType {
}
@@ -108,7 +108,7 @@ public final class WalletCard implements Parcelable {
PendingIntent.writePendingIntentOrNullToParcel(mPendingIntent, dest);
writeIconIfNonNull(mCardIcon, dest, flags);
TextUtils.writeToParcel(mCardLabel, dest, flags);
- writeIconIfNonNull(mValuableCardSecondaryImage, dest, flags);
+ writeIconIfNonNull(mNonPaymentCardSecondaryImage, dest, flags);
}
@@ -131,14 +131,14 @@ public final class WalletCard implements Parcelable {
PendingIntent pendingIntent = PendingIntent.readPendingIntentOrNullFromParcel(source);
Icon cardIcon = source.readByte() == 0 ? null : Icon.CREATOR.createFromParcel(source);
CharSequence cardLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- Icon valuableCardSecondaryImage = source.readByte() == 0 ? null :
+ Icon nonPaymentCardSecondaryImage = source.readByte() == 0 ? null :
Icon.CREATOR.createFromParcel(source);
Builder builder = new Builder(cardId, cardType, cardImage, contentDesc, pendingIntent)
.setCardIcon(cardIcon)
.setCardLabel(cardLabel);
- return cardType == CARD_TYPE_VALUABLE
- ? builder.setValuableCardSecondaryImage(valuableCardSecondaryImage).build() :
+ return cardType == CARD_TYPE_NON_PAYMENT
+ ? builder.setNonPaymentCardSecondaryImage(nonPaymentCardSecondaryImage).build() :
builder.build();
}
@@ -229,13 +229,13 @@ public final class WalletCard implements Parcelable {
}
/**
- * Visual representation of the card when it is tapped. Includes a barcode to scan the card in
- * addition to the information in the primary image.
+ * Visual representation of the card when it is tapped. May include additional information
+ * unique to the card, such as a barcode or number. Only valid for CARD_TYPE_NON_PAYMENT.
* @hide
- */
+ */
@Nullable
- public Icon getValuableCardSecondaryImage() {
- return mValuableCardSecondaryImage;
+ public Icon getNonPaymentCardSecondaryImage() {
+ return mNonPaymentCardSecondaryImage;
}
/**
@@ -251,7 +251,7 @@ public final class WalletCard implements Parcelable {
private PendingIntent mPendingIntent;
private Icon mCardIcon;
private CharSequence mCardLabel;
- private Icon mValuableCardSecondaryImage;
+ private Icon mNonPaymentCardSecondaryImage;
/**
* @param cardId The card id must be non-null and unique within the list of
@@ -259,7 +259,7 @@ public final class WalletCard implements Parcelable {
* </b> this card ID should <b>not</b> contain PII (Personally
* Identifiable Information, such as username or email address).
* @param cardType Integer representing the card type. The card type must be
- * non-null. If not provided, it defaults to unknown.
+ * non-null.
* @param cardImage The visual representation of the card. If the card image Icon
* is a bitmap, it should have a width of {@link
* GetWalletCardsRequest#getCardWidthPx()} and a height of {@link
@@ -294,7 +294,7 @@ public final class WalletCard implements Parcelable {
}
/**
- * Called when a card type is not provided.
+ * Called when a card type is not provided, in which case it defaults to CARD_TYPE_UNKNOWN.
*/
public Builder(@NonNull String cardId,
@NonNull Icon cardImage,
@@ -336,15 +336,16 @@ public final class WalletCard implements Parcelable {
}
/**
- * Visual representation of the card when it is tapped. Includes a barcode to scan the card
- * in addition to the information in the primary image.
+ * Visual representation of the card when it is tapped. May include additional information
+ * unique to the card, such as a barcode or number. Only valid for CARD_TYPE_NON_PAYMENT.
* @hide
*/
@NonNull
- public Builder setValuableCardSecondaryImage(@Nullable Icon valuableCardSecondaryImage) {
- Preconditions.checkState(mCardType == CARD_TYPE_VALUABLE,
- "This field can only be set on valuable cards");
- mValuableCardSecondaryImage = valuableCardSecondaryImage;
+ public Builder
+ setNonPaymentCardSecondaryImage(@Nullable Icon nonPaymentCardSecondaryImage) {
+ Preconditions.checkState(mCardType == CARD_TYPE_NON_PAYMENT,
+ "This field can only be set on non-payment cards");
+ mNonPaymentCardSecondaryImage = nonPaymentCardSecondaryImage;
return this;
}
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 506b3b81eb9a..81c5796374af 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -506,7 +506,7 @@ public class TileService extends Service {
* the calling package or if the calling user cannot act on behalf of the user from the
* {@code context}.</li>
* <li> {@link IllegalArgumentException} if the user of the {@code context} is not the
- * current user.</li>
+ * current user. Only thrown for apps targeting {@link Build.VERSION_CODES#TIRAMISU}</li>
* </ul>
*/
public static final void requestListeningState(Context context, ComponentName component) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d7480e5037f4..543a22b0f4d0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8774,7 +8774,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
@UnsupportedAppUsage
- public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
+ @TestApi
+ public void getBoundsOnScreen(@NonNull Rect outRect, boolean clipToParent) {
if (mAttachInfo == null) {
return;
}
@@ -8782,6 +8783,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
getBoundsToScreenInternal(position, clipToParent);
outRect.set(Math.round(position.left), Math.round(position.top),
Math.round(position.right), Math.round(position.bottom));
+ // If "Sandboxing View Bounds APIs" override is enabled, applyViewBoundsSandboxingIfNeeded
+ // will sandbox outRect within window bounds.
+ mAttachInfo.mViewRootImpl.applyViewBoundsSandboxingIfNeeded(outRect);
}
/**
@@ -15586,7 +15590,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
@UnsupportedAppUsage
- public void getWindowDisplayFrame(Rect outRect) {
+ @TestApi
+ public void getWindowDisplayFrame(@NonNull Rect outRect) {
if (mAttachInfo != null) {
mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
return;
@@ -25786,6 +25791,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (info != null) {
outLocation[0] += info.mWindowLeft;
outLocation[1] += info.mWindowTop;
+ // If OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS override is enabled,
+ // applyViewLocationSandboxingIfNeeded sandboxes outLocation within window bounds.
+ info.mViewRootImpl.applyViewLocationSandboxingIfNeeded(outLocation);
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 953f17a3a827..f6211fd488d8 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.content.pm.ActivityInfo.OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS;
import static android.graphics.HardwareRenderer.SYNC_CONTEXT_IS_STOPPED;
import static android.graphics.HardwareRenderer.SYNC_LOST_SURFACE_REWARD_IF_FOUND;
import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID;
@@ -82,6 +83,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
@@ -94,12 +96,14 @@ import android.animation.LayoutTransition;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.Size;
import android.annotation.UiContext;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ICompatCameraControlCallback;
import android.app.ResourcesManager;
import android.app.WindowConfiguration;
+import android.app.compat.CompatChanges;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ClipDescription;
@@ -871,6 +875,15 @@ public final class ViewRootImpl implements ViewParent,
private boolean mRelayoutRequested;
+ /**
+ * Whether sandboxing of {@link android.view.View#getBoundsOnScreen},
+ * {@link android.view.View#getLocationOnScreen(int[])},
+ * {@link android.view.View#getWindowDisplayFrame} and
+ * {@link android.view.View#getWindowVisibleDisplayFrame}
+ * within Activity bounds is enabled for the current application.
+ */
+ private final boolean mViewBoundsSandboxingEnabled;
+
private int mLastTransformHint = Integer.MIN_VALUE;
/**
@@ -958,6 +971,8 @@ public final class ViewRootImpl implements ViewParent,
mHandwritingInitiator = new HandwritingInitiator(mViewConfiguration,
mContext.getSystemService(InputMethodManager.class));
+ mViewBoundsSandboxingEnabled = getViewBoundsSandboxingEnabled();
+
String processorOverrideName = context.getResources().getString(
R.string.config_inputEventCompatProcessorOverrideClassName);
if (processorOverrideName.isEmpty()) {
@@ -8426,6 +8441,9 @@ public final class ViewRootImpl implements ViewParent,
*/
void getDisplayFrame(Rect outFrame) {
outFrame.set(mTmpFrames.displayFrame);
+ // Apply sandboxing here (in getter) due to possible layout updates on the client after
+ // mTmpFrames.displayFrame is received from the server.
+ applyViewBoundsSandboxingIfNeeded(outFrame);
}
/**
@@ -8442,6 +8460,69 @@ public final class ViewRootImpl implements ViewParent,
outFrame.top += insets.top;
outFrame.right -= insets.right;
outFrame.bottom -= insets.bottom;
+ // Apply sandboxing here (in getter) due to possible layout updates on the client after
+ // mTmpFrames.displayFrame is received from the server.
+ applyViewBoundsSandboxingIfNeeded(outFrame);
+ }
+
+ /**
+ * Offset outRect to make it sandboxed within Window's bounds.
+ *
+ * <p>This is used by {@link android.view.View#getBoundsOnScreen},
+ * {@link android.view.ViewRootImpl#getDisplayFrame} and
+ * {@link android.view.ViewRootImpl#getWindowVisibleDisplayFrame}, which are invoked by
+ * {@link android.view.View#getWindowDisplayFrame} and
+ * {@link android.view.View#getWindowVisibleDisplayFrame}, as well as
+ * {@link android.view.ViewDebug#captureLayers} for debugging.
+ */
+ void applyViewBoundsSandboxingIfNeeded(final Rect inOutRect) {
+ if (mViewBoundsSandboxingEnabled) {
+ final Rect bounds = getConfiguration().windowConfiguration.getBounds();
+ inOutRect.offset(-bounds.left, -bounds.top);
+ }
+ }
+
+ /**
+ * Offset outLocation to make it sandboxed within Window's bounds.
+ *
+ * <p>This is used by {@link android.view.View#getLocationOnScreen(int[])}
+ */
+ public void applyViewLocationSandboxingIfNeeded(@Size(2) int[] outLocation) {
+ if (mViewBoundsSandboxingEnabled) {
+ final Rect bounds = getConfiguration().windowConfiguration.getBounds();
+ outLocation[0] -= bounds.left;
+ outLocation[1] -= bounds.top;
+ }
+ }
+
+ private boolean getViewBoundsSandboxingEnabled() {
+ // System dialogs (e.g. ANR) can be created within System process, so handleBindApplication
+ // may be never called. This results into all app compat changes being enabled
+ // (see b/268007823) because AppCompatCallbacks.install() is never called with non-empty
+ // array.
+ // With ActivityThread.isSystem we verify that it is not the system process,
+ // then this CompatChange can take effect.
+ if (ActivityThread.isSystem()
+ || !CompatChanges.isChangeEnabled(OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS)) {
+ // It is a system process or OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS change-id is disabled.
+ return false;
+ }
+
+ // OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS is enabled by the device manufacturer.
+ try {
+ final List<PackageManager.Property> properties = mContext.getPackageManager()
+ .queryApplicationProperty(PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS);
+
+ final boolean isOptedOut = !properties.isEmpty() && !properties.get(0).getBoolean();
+ if (isOptedOut) {
+ // PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS is disabled by the app devs.
+ return false;
+ }
+ } catch (RuntimeException e) {
+ // remote exception.
+ }
+
+ return true;
}
/**
@@ -9883,9 +9964,12 @@ public final class ViewRootImpl implements ViewParent,
}
void checkThread() {
- if (mThread != Thread.currentThread()) {
+ Thread current = Thread.currentThread();
+ if (mThread != current) {
throw new CalledFromWrongThreadException(
- "Only the original thread that created a view hierarchy can touch its views.");
+ "Only the original thread that created a view hierarchy can touch its views."
+ + " Expected: " + mThread.getName()
+ + " Calling: " + current.getName());
}
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 02027e4a3969..293f9082670d 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -823,6 +823,11 @@ public abstract class Window {
/** @hide */
public final void destroy() {
mDestroyed = true;
+ onDestroy();
+ }
+
+ /** @hide */
+ protected void onDestroy() {
}
/** @hide */
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 17df585e424a..a01c8328b37c 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -854,6 +854,42 @@ public interface WindowManager extends ViewManager {
/**
* Application level {@link android.content.pm.PackageManager.Property PackageManager
+ * .Property} for an app to inform the system that it needs to be opted-out from the
+ * compatibility treatment that sandboxes {@link android.view.View} API.
+ *
+ * <p>The treatment can be enabled by device manufacturers for applications which misuse
+ * {@link android.view.View} APIs by expecting that
+ * {@link android.view.View#getLocationOnScreen},
+ * {@link android.view.View#getBoundsOnScreen},
+ * {@link android.view.View#getWindowVisibleDisplayFrame},
+ * {@link android.view.View#getWindowDisplayFrame}
+ * return coordinates as if an activity is positioned in the top-left corner of the screen, with
+ * left coordinate equal to 0. This may not be the case for applications in multi-window and in
+ * letterbox modes.
+ *
+ * <p>Setting this property to {@code false} informs the system that the application must be
+ * opted-out from the "Sandbox {@link android.view.View} API to Activity bounds" treatment even
+ * if the device manufacturer has opted the app into the treatment.
+ *
+ * <p>Not setting this property at all, or setting this property to {@code true} has no effect.
+ *
+ * <p><b>Syntax:</b>
+ * <pre>
+ * &lt;application&gt;
+ * &lt;property
+ * android:name="android.window.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS"
+ * android:value="false"/&gt;
+ * &lt;/application&gt;
+ * </pre>
+ *
+ * @hide
+ */
+ // TODO(b/263984287): Make this public API.
+ String PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS =
+ "android.window.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS";
+
+ /**
+ * Application level {@link android.content.pm.PackageManager.Property PackageManager
* .Property} for an app to inform the system that the application can be opted-in or opted-out
* from the compatibility treatment that enables sending a fake focus event for unfocused
* resumed split screen activities. This is needed because some game engines wait to get
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 011232fe1915..cef5120bc0b7 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -21,6 +21,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL;
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK;
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
+import static android.content.ContentProvider.getUserIdFromUri;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
@@ -161,6 +162,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
/**
* The Chooser Activity handles intent resolution specifically for sharing intents -
@@ -1424,7 +1426,11 @@ public class ChooserActivity extends ResolverActivity implements
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
- Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
+ Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM, android.net.Uri.class);
+ if (!validForContentPreview(uri)) {
+ contentPreviewLayout.setVisibility(View.GONE);
+ return contentPreviewLayout;
+ }
imagePreview.findViewById(R.id.content_preview_image_1_large)
.setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0);
@@ -1434,7 +1440,7 @@ public class ChooserActivity extends ResolverActivity implements
List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
List<Uri> imageUris = new ArrayList<>();
for (Uri uri : uris) {
- if (isImageType(resolver.getType(uri))) {
+ if (validForContentPreview(uri) && isImageType(resolver.getType(uri))) {
imageUris.add(uri);
}
}
@@ -1544,9 +1550,16 @@ public class ChooserActivity extends ResolverActivity implements
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
+ if (!validForContentPreview(uri)) {
+ contentPreviewLayout.setVisibility(View.GONE);
+ return contentPreviewLayout;
+ }
loadFileUriIntoView(uri, contentPreviewLayout);
} else {
List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
+ uris = uris.stream()
+ .filter(ChooserActivity::validForContentPreview)
+ .collect(Collectors.toList());
int uriCount = uris.size();
if (uriCount == 0) {
@@ -1605,6 +1618,24 @@ public class ChooserActivity extends ResolverActivity implements
}
}
+ /**
+ * Indicate if the incoming content URI should be allowed.
+ *
+ * @param uri the uri to test
+ * @return true if the URI is allowed for content preview
+ */
+ private static boolean validForContentPreview(Uri uri) throws SecurityException {
+ if (uri == null) {
+ return false;
+ }
+ int userId = getUserIdFromUri(uri, UserHandle.USER_CURRENT);
+ if (userId != UserHandle.USER_CURRENT && userId != UserHandle.myUserId()) {
+ Log.e(TAG, "dropped invalid content URI belonging to user " + userId);
+ return false;
+ }
+ return true;
+ }
+
@VisibleForTesting
protected boolean isImageType(String mimeType) {
return mimeType != null && mimeType.startsWith("image/");
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index 72b9cd272d02..818a50366115 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -73,6 +73,7 @@ import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection;
import java.io.PrintWriter;
import java.util.Comparator;
+import java.util.concurrent.TimeUnit;
public final class ProcessState {
private static final String TAG = "ProcessStats";
@@ -1542,6 +1543,75 @@ public final class ProcessState {
proto.write(fieldId, procName);
}
+ /** Dumps the duration of each state to statsEventOutput. */
+ public void dumpStateDurationToStatsd(
+ int atomTag, ProcessStats processStats, StatsEventOutput statsEventOutput) {
+ long topMs = 0;
+ long fgsMs = 0;
+ long boundTopMs = 0;
+ long boundFgsMs = 0;
+ long importantForegroundMs = 0;
+ long cachedMs = 0;
+ long frozenMs = 0;
+ long otherMs = 0;
+ for (int i = 0, size = mDurations.getKeyCount(); i < size; i++) {
+ final int key = mDurations.getKeyAt(i);
+ final int type = SparseMappingTable.getIdFromKey(key);
+ int procStateIndex = type % STATE_COUNT;
+ long duration = mDurations.getValue(key);
+ switch (procStateIndex) {
+ case STATE_TOP:
+ topMs += duration;
+ break;
+ case STATE_BOUND_TOP_OR_FGS:
+ boundTopMs += duration;
+ break;
+ case STATE_FGS:
+ fgsMs += duration;
+ break;
+ case STATE_IMPORTANT_FOREGROUND:
+ case STATE_IMPORTANT_BACKGROUND:
+ importantForegroundMs += duration;
+ break;
+ case STATE_BACKUP:
+ case STATE_SERVICE:
+ case STATE_SERVICE_RESTARTING:
+ case STATE_RECEIVER:
+ case STATE_HEAVY_WEIGHT:
+ case STATE_HOME:
+ case STATE_LAST_ACTIVITY:
+ case STATE_PERSISTENT:
+ otherMs += duration;
+ break;
+ case STATE_CACHED_ACTIVITY:
+ case STATE_CACHED_ACTIVITY_CLIENT:
+ case STATE_CACHED_EMPTY:
+ cachedMs += duration;
+ break;
+ // TODO (b/261910877) Add support for tracking boundFgsMs and
+ // frozenMs.
+ }
+ }
+ statsEventOutput.write(
+ atomTag,
+ getUid(),
+ getName(),
+ (int) TimeUnit.MILLISECONDS.toSeconds(processStats.mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(processStats.mTimePeriodEndUptime),
+ (int)
+ TimeUnit.MILLISECONDS.toSeconds(
+ processStats.mTimePeriodEndUptime
+ - processStats.mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(topMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(fgsMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(boundTopMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(boundFgsMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(importantForegroundMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(cachedMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(frozenMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(otherMs));
+ }
+
/** Similar to {@code #dumpDebug}, but with a reduced/aggregated subset of states. */
public void dumpAggregatedProtoForStatsd(ProtoOutputStream proto, long fieldId,
String procName, int uid, long now,
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index d2b2f0a2b894..f3ed09a861e3 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -43,6 +43,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.procstats.AssociationState.SourceKey;
import com.android.internal.app.procstats.AssociationState.SourceState;
+import com.android.internal.util.function.QuintConsumer;
import dalvik.system.VMRuntime;
@@ -56,6 +57,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -2389,6 +2392,79 @@ public final class ProcessStats implements Parcelable {
}
}
+ void forEachProcess(Consumer<ProcessState> consumer) {
+ final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
+ for (int ip = 0, size = procMap.size(); ip < size; ip++) {
+ final SparseArray<ProcessState> uids = procMap.valueAt(ip);
+ for (int iu = 0, uidsSize = uids.size(); iu < uidsSize; iu++) {
+ final ProcessState processState = uids.valueAt(iu);
+ consumer.accept(processState);
+ }
+ }
+ }
+
+ void forEachAssociation(
+ QuintConsumer<AssociationState, Integer, String, SourceKey, SourceState> consumer) {
+ final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
+ mPackages.getMap();
+ for (int ip = 0, size = pkgMap.size(); ip < size; ip++) {
+ final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
+ for (int iu = 0, uidsSize = uids.size(); iu < uidsSize; iu++) {
+ final int uid = uids.keyAt(iu);
+ final LongSparseArray<PackageState> versions = uids.valueAt(iu);
+ for (int iv = 0, versionsSize = versions.size(); iv < versionsSize; iv++) {
+ final PackageState state = versions.valueAt(iv);
+ for (int iasc = 0, ascSize = state.mAssociations.size();
+ iasc < ascSize;
+ iasc++) {
+ final String serviceName = state.mAssociations.keyAt(iasc);
+ final AssociationState asc = state.mAssociations.valueAt(iasc);
+ for (int is = 0, sourcesSize = asc.mSources.size();
+ is < sourcesSize;
+ is++) {
+ final SourceState src = asc.mSources.valueAt(is);
+ final SourceKey key = asc.mSources.keyAt(is);
+ consumer.accept(asc, uid, serviceName, key, src);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /** Dumps the stats of all processes to statsEventOutput. */
+ public void dumpProcessState(int atomTag, StatsEventOutput statsEventOutput) {
+ forEachProcess(
+ (processState) -> {
+ if (processState.isMultiPackage()
+ && processState.getCommonProcess() != processState) {
+ return;
+ }
+ processState.dumpStateDurationToStatsd(atomTag, this, statsEventOutput);
+ });
+ }
+
+ /** Dumps all process association data to statsEventOutput. */
+ public void dumpProcessAssociation(int atomTag, StatsEventOutput statsEventOutput) {
+ forEachAssociation(
+ (asc, serviceUid, serviceName, key, src) -> {
+ statsEventOutput.write(
+ atomTag,
+ key.mUid,
+ key.mProcess,
+ serviceUid,
+ serviceName,
+ (int) TimeUnit.MILLISECONDS.toSeconds(mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(mTimePeriodEndUptime),
+ (int)
+ TimeUnit.MILLISECONDS.toSeconds(
+ mTimePeriodEndUptime - mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(src.mDuration),
+ src.mActiveCount,
+ asc.getProcessName());
+ });
+ }
+
private void dumpProtoPreamble(ProtoOutputStream proto) {
proto.write(ProcessStatsSectionProto.START_REALTIME_MS, mTimePeriodStartRealtime);
proto.write(ProcessStatsSectionProto.END_REALTIME_MS,
diff --git a/core/java/com/android/internal/app/procstats/StatsEventOutput.java b/core/java/com/android/internal/app/procstats/StatsEventOutput.java
new file mode 100644
index 000000000000..b2e405475a4e
--- /dev/null
+++ b/core/java/com/android/internal/app/procstats/StatsEventOutput.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app.procstats;
+
+import android.util.StatsEvent;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.util.List;
+
+/**
+ * A simple wrapper of FrameworkStatsLog.buildStatsEvent. This allows unit tests to mock out the
+ * dependency.
+ */
+public class StatsEventOutput {
+
+ List<StatsEvent> mOutput;
+
+ public StatsEventOutput(List<StatsEvent> output) {
+ mOutput = output;
+ }
+
+ /** Writes the data to the output. */
+ public void write(
+ int atomTag,
+ int uid,
+ String processName,
+ int measurementStartUptimeSecs,
+ int measurementEndUptimeSecs,
+ int measurementDurationUptimeSecs,
+ int topSeconds,
+ int fgsSeconds,
+ int boundTopSeconds,
+ int boundFgsSeconds,
+ int importantForegroundSeconds,
+ int cachedSeconds,
+ int frozenSeconds,
+ int otherSeconds) {
+ mOutput.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ uid,
+ processName,
+ measurementStartUptimeSecs,
+ measurementEndUptimeSecs,
+ measurementDurationUptimeSecs,
+ topSeconds,
+ fgsSeconds,
+ boundTopSeconds,
+ boundFgsSeconds,
+ importantForegroundSeconds,
+ cachedSeconds,
+ frozenSeconds,
+ otherSeconds));
+ }
+
+ /** Writes the data to the output. */
+ public void write(
+ int atomTag,
+ int clientUid,
+ String processName,
+ int serviceUid,
+ String serviceName,
+ int measurementStartUptimeSecs,
+ int measurementEndUptimeSecs,
+ int measurementDurationUptimeSecs,
+ int activeDurationUptimeSecs,
+ int activeCount,
+ String serviceProcessName) {
+ mOutput.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ clientUid,
+ processName,
+ serviceUid,
+ serviceName,
+ measurementStartUptimeSecs,
+ measurementEndUptimeSecs,
+ measurementDurationUptimeSecs,
+ activeDurationUptimeSecs,
+ activeCount,
+ serviceProcessName));
+ }
+}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index d8afe50d3af3..e7217def7689 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -33,6 +33,7 @@ import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_IN
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_OCCLUSION;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR;
@@ -231,6 +232,7 @@ public class InteractionJankMonitor {
public static final int CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS = 66;
public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE = 67;
public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME = 68;
+ public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = 70;
private static final int NO_STATSD_LOGGING = -1;
@@ -308,6 +310,8 @@ public class InteractionJankMonitor {
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
+ NO_STATSD_LOGGING,
+ UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION,
};
private static volatile InteractionJankMonitor sInstance;
@@ -396,7 +400,8 @@ public class InteractionJankMonitor {
CUJ_RECENTS_SCROLLING,
CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS,
CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE,
- CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME
+ CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
+ CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION
})
@Retention(RetentionPolicy.SOURCE)
public @interface CujType {
@@ -917,6 +922,8 @@ public class InteractionJankMonitor {
return "LAUNCHER_CLOSE_ALL_APPS_SWIPE";
case CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME:
return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME";
+ case CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION:
+ return "LOCKSCREEN_CLOCK_MOVE_ANIMATION";
}
return "UNKNOWN";
}
diff --git a/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java b/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
index d2b612a9e6f3..f1ed3bed5d89 100644
--- a/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
+++ b/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
@@ -56,6 +56,9 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
}
};
+ /**
+ * Registers the observer for all users.
+ */
public void register() {
ContentResolver r = mContext.getContentResolver();
r.registerContentObserver(
@@ -73,7 +76,10 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
mOnPropertiesChangedListener);
}
- public void registerForCurrentUser() {
+ /**
+ * Registers the observer for the calling user.
+ */
+ public void registerForCallingUser() {
ContentResolver r = mContext.getContentResolver();
r.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT),
@@ -103,12 +109,46 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
}
}
+ /**
+ * Returns the left sensitivity for the current user. To be used in code that runs primarily
+ * in one user's process.
+ */
public int getLeftSensitivity(Resources userRes) {
- return getSensitivity(userRes, Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT);
+ final float scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT, 1.0f, UserHandle.USER_CURRENT);
+ return (int) (getUnscaledInset(userRes) * scale);
}
+ /**
+ * Returns the left sensitivity for the calling user. To be used in code that runs in a
+ * per-user process.
+ */
+ @SuppressWarnings("NonUserGetterCalled")
+ public int getLeftSensitivityForCallingUser(Resources userRes) {
+ final float scale = Settings.Secure.getFloat(mContext.getContentResolver(),
+ Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT, 1.0f);
+ return (int) (getUnscaledInset(userRes) * scale);
+ }
+
+ /**
+ * Returns the right sensitivity for the current user. To be used in code that runs primarily
+ * in one user's process.
+ */
public int getRightSensitivity(Resources userRes) {
- return getSensitivity(userRes, Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT);
+ final float scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT, 1.0f, UserHandle.USER_CURRENT);
+ return (int) (getUnscaledInset(userRes) * scale);
+ }
+
+ /**
+ * Returns the right sensitivity for the calling user. To be used in code that runs in a
+ * per-user process.
+ */
+ @SuppressWarnings("NonUserGetterCalled")
+ public int getRightSensitivityForCallingUser(Resources userRes) {
+ final float scale = Settings.Secure.getFloat(mContext.getContentResolver(),
+ Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT, 1.0f);
+ return (int) (getUnscaledInset(userRes) * scale);
}
public boolean areNavigationButtonForcedVisible() {
@@ -116,7 +156,7 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) == 0;
}
- private int getSensitivity(Resources userRes, String side) {
+ private float getUnscaledInset(Resources userRes) {
final DisplayMetrics dm = userRes.getDisplayMetrics();
final float defaultInset = userRes.getDimension(
com.android.internal.R.dimen.config_backGestureInset) / dm.density;
@@ -127,8 +167,6 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
: defaultInset;
final float inset = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, backGestureInset,
dm);
- final float scale = Settings.Secure.getFloatForUser(
- mContext.getContentResolver(), side, 1.0f, UserHandle.USER_CURRENT);
- return (int) (inset * scale);
+ return inset;
}
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index bb69192f187f..e603e2ed57f1 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -295,6 +295,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private boolean mClosingActionMenu;
private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
+ private int mAudioMode = AudioManager.MODE_NORMAL;
private MediaController mMediaController;
private AudioManager mAudioManager;
@@ -317,6 +318,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
};
+ private AudioManager.OnModeChangedListener mOnModeChangedListener;
+
private Transition mEnterTransition = null;
private Transition mReturnTransition = USE_DEFAULT_TRANSITION;
private Transition mExitTransition = null;
@@ -1950,9 +1953,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
- // If we have a session send it the volume command, otherwise
- // use the suggested stream.
- if (mMediaController != null) {
+ // If we have a session and no active phone call send it the volume command,
+ // otherwise use the suggested stream.
+ if (mMediaController != null && !isActivePhoneCallOngoing()) {
getMediaSessionManager().dispatchVolumeKeyEventToSessionAsSystemService(event,
mMediaController.getSessionToken());
} else {
@@ -2003,6 +2006,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return false;
}
+ private boolean isActivePhoneCallOngoing() {
+ return mAudioMode == AudioManager.MODE_IN_CALL
+ || mAudioMode == AudioManager.MODE_IN_COMMUNICATION;
+ }
+
private KeyguardManager getKeyguardManager() {
if (mKeyguardManager == null) {
mKeyguardManager = (KeyguardManager) getContext().getSystemService(
@@ -2326,6 +2334,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
+ @Override
+ protected void onDestroy() {
+ if (mOnModeChangedListener != null) {
+ getAudioManager().removeOnModeChangedListener(mOnModeChangedListener);
+ mOnModeChangedListener = null;
+ }
+ }
+
private class PanelMenuPresenterCallback implements MenuPresenter.Callback {
@Override
public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
@@ -3208,6 +3224,15 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
@Override
public void setMediaController(MediaController controller) {
mMediaController = controller;
+ if (controller != null && mOnModeChangedListener == null) {
+ mAudioMode = getAudioManager().getMode();
+ mOnModeChangedListener = mode -> mAudioMode = mode;
+ getAudioManager().addOnModeChangedListener(getContext().getMainExecutor(),
+ mOnModeChangedListener);
+ } else if (mOnModeChangedListener != null) {
+ getAudioManager().removeOnModeChangedListener(mOnModeChangedListener);
+ mOnModeChangedListener = null;
+ }
}
@Override
diff --git a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java b/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
index 83309fc61009..ac9188a0debc 100644
--- a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
@@ -72,11 +72,13 @@ public class BaseProtoLogImpl {
private static final String TAG = "ProtoLog";
private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
static final String PROTOLOG_VERSION = "1.0.0";
+ private static final int DEFAULT_PER_CHUNK_SIZE = 0;
private final File mLogFile;
private final String mViewerConfigFilename;
private final TraceBuffer mBuffer;
protected final ProtoLogViewerConfigReader mViewerConfig;
+ private final int mPerChunkSize;
private boolean mProtoLogEnabled;
private boolean mProtoLogEnabledLockFree;
@@ -156,7 +158,7 @@ public class BaseProtoLogImpl {
return;
}
try {
- ProtoOutputStream os = new ProtoOutputStream();
+ ProtoOutputStream os = new ProtoOutputStream(mPerChunkSize);
long token = os.start(LOG);
os.write(MESSAGE_HASH, messageHash);
os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos());
@@ -215,10 +217,16 @@ public class BaseProtoLogImpl {
public BaseProtoLogImpl(File file, String viewerConfigFilename, int bufferCapacity,
ProtoLogViewerConfigReader viewerConfig) {
+ this(file, viewerConfigFilename, bufferCapacity, viewerConfig, DEFAULT_PER_CHUNK_SIZE);
+ }
+
+ public BaseProtoLogImpl(File file, String viewerConfigFilename, int bufferCapacity,
+ ProtoLogViewerConfigReader viewerConfig, int perChunkSize) {
mLogFile = file;
mBuffer = new TraceBuffer(bufferCapacity);
mViewerConfigFilename = viewerConfigFilename;
mViewerConfig = viewerConfig;
+ mPerChunkSize = perChunkSize;
}
/**
@@ -255,6 +263,7 @@ public class BaseProtoLogImpl {
if (writeToFile) {
writeProtoLogToFileLocked();
logAndPrintln(pw, "Log written to " + mLogFile + ".");
+ mBuffer.resetBuffer();
}
if (mProtoLogEnabled) {
logAndPrintln(pw, "ERROR: logging was re-enabled while waiting for flush.");
@@ -363,7 +372,7 @@ public class BaseProtoLogImpl {
try {
long offset =
(System.currentTimeMillis() - (SystemClock.elapsedRealtimeNanos() / 1000000));
- ProtoOutputStream proto = new ProtoOutputStream();
+ ProtoOutputStream proto = new ProtoOutputStream(mPerChunkSize);
proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE);
proto.write(VERSION, PROTOLOG_VERSION);
proto.write(REAL_TIME_TO_ELAPSED_TIME_OFFSET_MILLIS, offset);
diff --git a/core/java/com/android/internal/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java
index 353c6c083d9d..527cfddf6d8e 100644
--- a/core/java/com/android/internal/protolog/ProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java
@@ -30,6 +30,7 @@ public class ProtoLogImpl extends BaseProtoLogImpl {
private static final int BUFFER_CAPACITY = 1024 * 1024;
private static final String LOG_FILENAME = "/data/misc/wmtrace/wm_log.winscope";
private static final String VIEWER_CONFIG_FILENAME = "/system/etc/protolog.conf.json.gz";
+ private static final int PER_CHUNK_SIZE = 1024;
private static ProtoLogImpl sServiceInstance = null;
@@ -94,7 +95,10 @@ public class ProtoLogImpl extends BaseProtoLogImpl {
public static synchronized ProtoLogImpl getSingleInstance() {
if (sServiceInstance == null) {
sServiceInstance = new ProtoLogImpl(
- new File(LOG_FILENAME), BUFFER_CAPACITY, new ProtoLogViewerConfigReader());
+ new File(LOG_FILENAME)
+ , BUFFER_CAPACITY
+ , new ProtoLogViewerConfigReader()
+ , PER_CHUNK_SIZE);
}
return sServiceInstance;
}
@@ -105,8 +109,8 @@ public class ProtoLogImpl extends BaseProtoLogImpl {
}
public ProtoLogImpl(File logFile, int bufferCapacity,
- ProtoLogViewerConfigReader viewConfigReader) {
- super(logFile, VIEWER_CONFIG_FILENAME, bufferCapacity, viewConfigReader);
- }
+ ProtoLogViewerConfigReader viewConfigReader, int perChunkSize) {
+ super(logFile, VIEWER_CONFIG_FILENAME, bufferCapacity, viewConfigReader, perChunkSize);
+ }
}
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index afb526aeea6f..fe08083282c5 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -24,12 +24,15 @@ import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPOR
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FOLD_TO_AOD;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOAD_SHARE_SHEET;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOCKSCREEN_UNLOCK;
+import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN;
+import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_CAMERA_CHECK;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_SENSOR;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_BACK_ARROW;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_SELECTION_TOOLBAR;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_VOICE_INTERACTION;
+import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SMARTSPACE_DOORBELL;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_START_RECENTS_ANIMATION;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SWITCH_DISPLAY_UNFOLD;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_TOGGLE_RECENTS;
@@ -187,6 +190,25 @@ public class LatencyTracker {
*/
public static final int ACTION_SHOW_VOICE_INTERACTION = 19;
+ /**
+ * Time it takes to request IME shown animation.
+ */
+ public static final int ACTION_REQUEST_IME_SHOWN = 20;
+
+ /**
+ * Time it takes to request IME hidden animation.
+ */
+ public static final int ACTION_REQUEST_IME_HIDDEN = 21;
+
+ /**
+ * Time it takes to load the animation frames in smart space doorbell card.
+ * It measures the duration from the images uris are passed into the view
+ * to all the frames are loaded.
+ * <p/>
+ * A long latency makes the doorbell animation looks janky until all the frames are loaded.
+ */
+ public static final int ACTION_SMARTSPACE_DOORBELL = 22;
+
private static final int[] ACTIONS_ALL = {
ACTION_EXPAND_PANEL,
ACTION_TOGGLE_RECENTS,
@@ -208,6 +230,9 @@ public class LatencyTracker {
ACTION_SHOW_SELECTION_TOOLBAR,
ACTION_FOLD_TO_AOD,
ACTION_SHOW_VOICE_INTERACTION,
+ ACTION_REQUEST_IME_SHOWN,
+ ACTION_REQUEST_IME_HIDDEN,
+ ACTION_SMARTSPACE_DOORBELL,
};
/** @hide */
@@ -232,6 +257,9 @@ public class LatencyTracker {
ACTION_SHOW_SELECTION_TOOLBAR,
ACTION_FOLD_TO_AOD,
ACTION_SHOW_VOICE_INTERACTION,
+ ACTION_REQUEST_IME_SHOWN,
+ ACTION_REQUEST_IME_HIDDEN,
+ ACTION_SMARTSPACE_DOORBELL,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Action {
@@ -259,6 +287,9 @@ public class LatencyTracker {
UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_SELECTION_TOOLBAR,
UIACTION_LATENCY_REPORTED__ACTION__ACTION_FOLD_TO_AOD,
UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_VOICE_INTERACTION,
+ UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN,
+ UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN,
+ UIACTION_LATENCY_REPORTED__ACTION__ACTION_SMARTSPACE_DOORBELL,
};
private static LatencyTracker sLatencyTracker;
@@ -368,6 +399,12 @@ public class LatencyTracker {
return "ACTION_FOLD_TO_AOD";
case UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_VOICE_INTERACTION:
return "ACTION_SHOW_VOICE_INTERACTION";
+ case UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN:
+ return "ACTION_REQUEST_IME_SHOWN";
+ case UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN:
+ return "ACTION_REQUEST_IME_HIDDEN";
+ case UIACTION_LATENCY_REPORTED__ACTION__ACTION_SMARTSPACE_DOORBELL:
+ return "ACTION_SMARTSPACE_DOORBELL";
default:
throw new IllegalArgumentException("Invalid action");
}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 556636ddd210..d443270575d3 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -89,6 +89,8 @@ message SecureSettingsProto {
// Setting for accessibility magnification for following typing.
optional SettingProto accessibility_magnification_follow_typing_enabled = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto contrast_level = 44 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Settings for font scaling
+ optional SettingProto accessibility_font_scaling_has_been_changed = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Accessibility accessibility = 2;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 31903e25f8fd..0e95e30a99b8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3154,7 +3154,11 @@
android:protectionLevel="normal" />
<!-- Allows an application to call
- {@link android.app.ActivityManager#killBackgroundProcesses}.
+ {@link android.app.ActivityManager#killBackgroundProcesses}.
+
+ <p class="note">Third party applications can only use this API to kill their own
+ processes.</p>
+
<p>Protection level: normal
-->
<permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"
diff --git a/core/res/res/layout/transient_notification.xml b/core/res/res/layout/transient_notification.xml
index 3259201f6e9b..8bedb897dc19 100644
--- a/core/res/res/layout/transient_notification.xml
+++ b/core/res/res/layout/transient_notification.xml
@@ -25,7 +25,7 @@
android:orientation="horizontal"
android:gravity="center_vertical"
android:maxWidth="@dimen/toast_width"
- android:background="?android:attr/toastFrameBackground"
+ android:background="?android:attr/colorBackground"
android:elevation="@dimen/toast_elevation"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
diff --git a/core/res/res/layout/transient_notification_with_icon.xml b/core/res/res/layout/transient_notification_with_icon.xml
index e9b17df75333..0dfb3adc8364 100644
--- a/core/res/res/layout/transient_notification_with_icon.xml
+++ b/core/res/res/layout/transient_notification_with_icon.xml
@@ -22,7 +22,7 @@
android:orientation="horizontal"
android:gravity="center_vertical"
android:maxWidth="@dimen/toast_width"
- android:background="?android:attr/toastFrameBackground"
+ android:background="?android:attr/colorBackground"
android:elevation="@dimen/toast_elevation"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 7372a7ecfef7..04e71721c64b 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan gebare vasvang wat op die toestel se vingerafdruksensor uitgevoer word."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Neem skermkiekie"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan \'n skermkiekie neem."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Voorskou, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"deaktiveer of verander statusbalk"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Laat die program toe om die statusbalk te deaktiveer en stelselikone by te voeg of te verwyder."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"wees die statusbalk"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 3310cec48579..65ce60910c73 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"በመሣሪያው የጣት አሻራ ዳሳሽ ላይ የተከናወኑ የጣት ምልክቶችን መያዝ ይችላል።"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ቅጽበታዊ ገጽ እይታን ያነሳል"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"የማሳያው ቅጽበታዊ ገጽ እይታን ማንሳት ይችላል።"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"ቅድመ ዕይታ፣ <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"የሁኔቴ አሞሌ አቦዝን ወይም ቀይር"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"የስርዓት አዶዎችን ወደ ሁኔታ አሞሌ ላለማስቻል ወይም ለማከል እና ለማስወገድ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"የሁኔታ አሞሌ መሆን"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 980986e976ba..d46d3306d9f1 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -346,8 +346,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"يمكن أن تلتقط الإيماءات من أداة استشعار بصمة الإصبع في الجهاز."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"أخذ لقطة شاشة"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"يمكن أخذ لقطة شاشة."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"نسخة حصرية، \"<xliff:g id="DREAM_NAME">%1$s</xliff:g>\""</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"إيقاف شريط الحالة أو تعديله"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"للسماح للتطبيق بإيقاف شريط الحالة أو إضافة رموز نظام وإزالتها."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"العمل كشريط للحالة"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 77f230505552..e2213d76c9e2 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ডিভাইচটোৰ ফিংগাৰপ্ৰিণ্ট ছেন্সৰত দিয়া নিৰ্দেশ বুজিব পাৰে।"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্ৰীনশ্বট লওক"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিছপ্লে’খনৰ এটা স্ক্ৰীনশ্বট ল\'ব পাৰে।"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"পূৰ্বদৰ্শন কৰক, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"স্থিতি দণ্ড অক্ষম কৰক বা সলনি কৰক"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"স্থিতি দণ্ড অক্ষম কৰিবলৈ বা ছিষ্টেম আইকন আঁতৰাবলৈ এপ্‌টোক অনুমতি দিয়ে।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দণ্ড হ\'ব পাৰে"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 534f1a0e9feb..ea8addecceac 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Cihazların barmaq izi sensorunda olan işarələri əldə edə bilər."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran şəkli çəkin"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran şəkli çəkilə bilər."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Önizləmə, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"status panelini deaktivləşdir və ya dəyişdir"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Tətbiqə status panelini deaktiv etməyə və ya sistem ikonalarını əlavə etmək və ya silmək imkanı verir."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"status paneli edin"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index ae8c663fecd6..940b09195f07 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Može da registruje pokrete na senzoru za otisak prsta na uređaju."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Napravi snimak ekrana"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Može da napravi snimak ekrana."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili izmena statusne trake"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Dozvoljava aplikaciji da onemogući statusnu traku ili da dodaje i uklanja sistemske ikone."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"funkcionisanje kao statusna traka"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 85bd8f9c871f..58e72a72f9ae 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -344,8 +344,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Можа распазнаваць жэсты на сканеры адбіткаў пальцаў прылады."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Зрабіць здымак экрана"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Можна зрабіць здымак экрана."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Перадпрагляд, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"адключаць ці змяняць радок стану"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"быць панэллю стану"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 424f2cfafe2b..523c8b536695 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да улавя жестовете, извършени върху сензора за отпечатъци на устройството."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Създаване на екранна снимка"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да създава екранни снимки."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Визуализация на „<xliff:g id="DREAM_NAME">%1$s</xliff:g>“"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"деактивиране или промяна на лентата на състоянието"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Разрешава на приложението да деактивира лентата на състоянието или да добавя и премахва системни икони."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"изпълняване на ролята на лента на състоянието"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index cc1e61618458..731000984cf2 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ডিভাইসের আঙ্গুলের ছাপের সেন্সরের উপরে ইঙ্গিত করলে বুঝতে পারে।"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্রিনশট নিন"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিসপ্লের একটি স্ক্রিনশট নিতে পারেন।"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"প্রিভিউ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"স্ট্যাটাস বার নিষ্ক্রিয় অথবা সংশোধন করে"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"অ্যাপ্লিকেশনকে স্ট্যাটাস বার অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দন্ডে থাকুন"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 34b20468383a..92195111b13e 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -2053,9 +2053,9 @@
<string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"IPAK OTVORI"</string>
<string name="harmful_app_warning_title" msgid="8794823880881113856">"Otkrivena je štetna aplikacija"</string>
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Dozvoliti aplikaciji <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> da pristupa svim zapisnicima uređaja?"</string>
- <string name="log_access_confirmation_allow" msgid="5302517782599389507">"Dozvoli jednokratan pristup"</string>
+ <string name="log_access_confirmation_allow" msgid="5302517782599389507">"Dozvoli jednokratni pristup"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Nemoj dozvoliti"</string>
- <string name="log_access_confirmation_body" product="default" msgid="1806692062668620735">"Zapisnici uređaja bilježe šta se dešava na uređaju. Aplikacije mogu koristiti te zapisnike da pronađu i isprave probleme.\n\nNeki zapisnici mogu sadržavati osjetljive podatke, zato pristup svim zapisnicima uređaja dozvolite samo aplikacijama kojima vjerujete. \n\nAko ne dozvolite ovoj aplikaciji da pristupa svim zapisnicima uređaja, ona i dalje može pristupati svojim zapisnicima. Proizvođač uređaja će možda i dalje biti u stanju pristupiti nekim zapisnicima ili podacima na uređaju."</string>
+ <string name="log_access_confirmation_body" product="default" msgid="1806692062668620735">"Zapisnici uređaja bilježe šta se dešava na uređaju. Aplikacije mogu koristiti te zapisnike pronađu i riješe probleme.\n\nNeki zapisnici mogu sadržavati osjetljive podatke, zato pristup svim zapisnicima uređaja dozvolite samo aplikacijama kojima vjerujete. \n\nAko ne dozvolite ovoj aplikaciji da pristupa svim zapisnicima uređaja, ona i dalje može pristupati svojim zapisnicima. Proizvođač uređaja će možda i dalje biti u stanju pristupiti nekim zapisnicima ili podacima na uređaju."</string>
<string name="log_access_confirmation_body" product="tv" msgid="7379536536425265262">"Zapisnici uređaja bilježe šta se dešava na uređaju. Aplikacije mogu koristiti te zapisnike da pronađu i riješe probleme.\n\nNeki zapisnici mogu sadržavati osjetljive podatke. Zbog toga pristup svim zapisnicima uređaja dozvolite samo aplikacijama koje smatrate pouzdanima. \n\nAko ne dozvolite ovoj aplikaciji da pristupa svim zapisnicima uređaja, ona i dalje može pristupati svojim zapisnicima. Proizvođač uređaja će možda i dalje moći pristupiti nekim zapisnicima ili podacima na uređaju.\n\nSaznajte više na g.co/android/devicelogs."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ne prikazuj ponovo"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Aplikacija <xliff:g id="APP_0">%1$s</xliff:g> želi prikazati isječke aplikacije <xliff:g id="APP_2">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 4744f440ebb4..57acf8bb0829 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pot capturar els gestos fets en el sensor d\'empremtes digitals del dispositiu."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fer una captura de pantalla"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pot fer una captura de la pantalla."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Previsualitza, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra d\'estat"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"aparèixer a la barra d\'estat"</string>
@@ -1327,8 +1326,8 @@
<string name="sms_control_yes" msgid="4858845109269524622">"Permet"</string>
<string name="sms_control_no" msgid="4845717880040355570">"Denega"</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; vol enviar un missatge a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
- <string name="sms_short_code_details" msgid="2723725738333388351">"Aquesta acció "<b>"pot produir càrrecs"</b>" al teu compte per a mòbils."</string>
- <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Aquesta acció produirà càrrecs al teu compte per a mòbils."</b></string>
+ <string name="sms_short_code_details" msgid="2723725738333388351">"Aquesta acció "<b>"pot produir càrrecs"</b>" al teu compte mòbil."</string>
+ <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Aquesta acció produirà càrrecs al teu compte mòbil."</b></string>
<string name="sms_short_code_confirm_allow" msgid="920477594325526691">"Envia"</string>
<string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"Cancel·la"</string>
<string name="sms_short_code_remember_choice" msgid="1374526438647744862">"Recorda la meva selecció"</string>
@@ -1367,7 +1366,7 @@
<string name="usb_power_notification_message" msgid="7284765627437897702">"S\'està carregant el dispositiu connectat. Toca per veure més opcions."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"S\'ha detectat un accessori d\'àudio analògic"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"El dispositiu connectat no és compatible amb aquest telèfon. Toca per obtenir més informació."</string>
- <string name="adb_active_notification_title" msgid="408390247354560331">"Depuració per USB activada"</string>
+ <string name="adb_active_notification_title" msgid="408390247354560331">"Depuració per USB connectada"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"Toca per desactivar la depuració per USB"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Selecciona per desactivar la depuració per USB"</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"S\'ha connectat la depuració sense fil"</string>
@@ -2056,8 +2055,8 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Vols permetre que <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> accedeixi a tots els registres del dispositiu?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Permet l\'accés únic"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"No permetis"</string>
- <string name="log_access_confirmation_body" product="default" msgid="1806692062668620735">"Els registres del dispositiu inclouen informació sobre tot allò que passa al teu dispositiu. Les aplicacions poden utilitzar aquests registres per detectar i corregir problemes.\n\nÉs possible que alguns registres continguin informació sensible; per això només has de donar-hi accés a les aplicacions de confiança. \n\nEncara que no permetis que aquesta aplicació pugui accedir a tots els registres del dispositiu, podrà accedir als seus propis registres. És possible que el fabricant del dispositiu també tingui accés a alguns registres o a informació del teu dispositiu."</string>
- <string name="log_access_confirmation_body" product="tv" msgid="7379536536425265262">"Els registres del dispositiu inclouen informació sobre tot allò que passa al teu dispositiu. Les aplicacions poden utilitzar aquests registres per detectar i corregir problemes.\n\nÉs possible que alguns registres continguin informació sensible; per això només has de donar-hi accés a les aplicacions de confiança. \n\nEncara que no permetis que aquesta aplicació accedeixi a tots els registres del dispositiu, podrà accedir als seus propis registres. És possible que el fabricant del dispositiu també tingui accés a alguns registres o a informació del teu dispositiu.\n\nObtén més informació a g.co/android/devicelogs."</string>
+ <string name="log_access_confirmation_body" product="default" msgid="1806692062668620735">"Els registres del dispositiu inclouen informació sobre tot allò que passa al teu dispositiu. Les aplicacions poden utilitzar aquests registres per detectar i corregir problemes.\n\nCom que és possible que alguns registres continguin informació sensible, et recomanem que només hi permetis l\'accés a les aplicacions de confiança. \n\nEncara que no permetis que aquesta aplicació accedeixi a tots els registres del dispositiu, podrà accedir als seus propis registres. És possible que el fabricant del dispositiu també tingui accés a alguns registres o a informació del teu dispositiu."</string>
+ <string name="log_access_confirmation_body" product="tv" msgid="7379536536425265262">"Els registres del dispositiu inclouen informació sobre tot allò que passa al teu dispositiu. Les aplicacions poden utilitzar aquests registres per detectar i corregir problemes.\n\nCom que és possible que alguns registres continguin informació sensible, et recomanem que només hi permetis l\'accés a les aplicacions de confiança. \n\nEncara que no permetis que aquesta aplicació accedeixi a tots els registres del dispositiu, podrà accedir als seus propis registres. És possible que el fabricant del dispositiu també tingui accés a alguns registres o a informació del teu dispositiu.\n\nObtén més informació a g.co/android/devicelogs."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"No tornis a mostrar"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> vol mostrar porcions de l\'aplicació <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Edita"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 99686911539b..9f67d084cc7f 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -344,8 +344,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dokáže rozpoznat gesta zadaná na snímači otisků prstů."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Pořídit snímek obrazovky"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Může pořídit snímek obrazovky."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Náhled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"zakázání či změny stavového řádku"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vydávání se za stavový řádek"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 7b04bc98120a..fd169f5d3dec 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan registrere bevægelser, der foretages på enhedens fingeraftrykssensor."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tag screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan tage et screenshot af skærmen."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller redigere statuslinje"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vær statusbjælken"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 7b78645fd4c1..42fb58f82058 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -296,7 +296,7 @@
<string name="foreground_service_multiple_separator" msgid="5002287361849863168">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
<string name="safeMode" msgid="8974401416068943888">"Abgesicherter Modus"</string>
<string name="android_system_label" msgid="5974767339591067210">"Android-System"</string>
- <string name="user_owner_label" msgid="8628726904184471211">"Zum persönlichen Profil wechseln"</string>
+ <string name="user_owner_label" msgid="8628726904184471211">"Zum privaten Profil wechseln"</string>
<string name="managed_profile_label" msgid="7316778766973512382">"Zum Arbeitsprofil wechseln"</string>
<string name="permgrouplab_contacts" msgid="4254143639307316920">"Kontakte"</string>
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"auf deine Kontakte zugreifen"</string>
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Erfasst Touch-Gesten auf dem Fingerabdrucksensor des Geräts."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot erstellen"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Es kann ein Screenshot des Displays erstellt werden."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Vorschau – <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"Statusleiste deaktivieren oder ändern"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"Statusleiste darstellen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 93128aa9ad7c..e83314cae495 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Μπορεί να αναγνωρίσει κινήσεις που εκτελούνται στον αισθητήρα δακτυλικού αποτυπώματος της συσκευής."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Λήψη στιγμιότυπου οθόνης"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Μπορεί να τραβήξει στιγμιότυπο της οθόνης."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Προεπισκόπηση, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"απενεργοποιεί ή να τροποποιεί την γραμμή κατάστασης"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ορίζεται ως γραμμή κατάστασης"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 817f00ea41ec..95ef903b36b5 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Capturará los gestos que se hacen en el sensor de huellas dactilares del dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tomar captura de pantalla"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede tomar capturas de pantalla."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o que agregue y elimine íconos del sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string>
@@ -1367,7 +1366,7 @@
<string name="usb_power_notification_message" msgid="7284765627437897702">"Cargando el dispositivo conectado. Presiona para ver más opciones."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Se detectó 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. Presiona para obtener más información."</string>
- <string name="adb_active_notification_title" msgid="408390247354560331">"Depuración por USB conectada"</string>
+ <string name="adb_active_notification_title" msgid="408390247354560331">"Depuración por USB activada"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"Presiona para desactivar"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Seleccionar para desactivar la depuración por USB"</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Se conectó la depuración inalámbrica"</string>
@@ -2057,7 +2056,7 @@
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Permitir acceso por única vez"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"No permitir"</string>
<string name="log_access_confirmation_body" product="default" msgid="1806692062668620735">"Los registros del dispositivo permiten documentar lo que sucede en él. Las apps pueden usar estos registros para encontrar y solucionar problemas.\n\nEs posible que algunos registros del dispositivo contengan información sensible, por lo que solo debes permitir que accedan a todos ellos las apps que sean de tu confianza. \n\nSi no permites que esta app acceda a todos los registros del dispositivo, aún puede acceder a sus propios registros. Además, es posible que el fabricante del dispositivo acceda a algunos registros o información en tu dispositivo."</string>
- <string name="log_access_confirmation_body" product="tv" msgid="7379536536425265262">"Los registros del dispositivo permiten documentar lo que sucede en él. Las apps pueden usar estos registros para encontrar y solucionar problemas.\n\nEs posible que algunos registros del dispositivo contengan información sensible, por lo que solo debes permitir que accedan a todos los registros las apps que sean de tu confianza. \n\nTen en cuenta que la app puede acceder a sus propios registros incluso si no permites que acceda a todos los registros del dispositivo. También es posible que el fabricante del dispositivo acceda a algunos registros o información en tu dispositivo.\n\nObtén más información en g.co/android/devicelogs."</string>
+ <string name="log_access_confirmation_body" product="tv" msgid="7379536536425265262">"Los registros del dispositivo permiten documentar lo que sucede en él. Las apps pueden usar estos registros para encontrar y solucionar problemas.\n\nEs posible que algunos registros del dispositivo contengan información sensible, por lo que solo debes permitir que accedan a ellos las apps que sean de tu confianza. \n\nTen en cuenta que la app puede acceder a sus propios registros incluso si no permites que acceda a todos los registros del dispositivo. También es posible que el fabricante del dispositivo acceda a algunos registros o información en tu dispositivo.\n\nObtén más información en g.co/android/devicelogs."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"No volver a mostrar"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> quiere mostrar fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Editar"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index ba30d42619e8..4f36d21c137d 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Puede capturar los gestos realizados en el sensor de huellas digitales del dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Hacer captura"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede hacer capturas de la pantalla."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"inhabilitar o modificar la barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o añada y elimine iconos del sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string>
@@ -1367,9 +1366,9 @@
<string name="usb_power_notification_message" msgid="7284765627437897702">"Cargando el dispositivo conectado. Toca para ver más opciones."</string>
<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 USB habilitada"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"Toca para desactivar la depuración USB"</string>
- <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Seleccionar para inhabilitar la depuración USB"</string>
+ <string name="adb_active_notification_title" msgid="408390247354560331">"Depuración por USB activa"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Toca para desactivar la depuración por 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>
<string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Toca para desactivar la depuración inalámbrica."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 18539dfd2eb1..22796f27ef56 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Teil on võimalik jäädvustada seadme sõrmejäljeanduril tehtud liigutused."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Jäädvusta ekraanipilt"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Saab jäädvustada ekraanipildi."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Eelvaade, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"keela või muuda olekuriba"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Võimaldab rakendusel keelata olekuriba või lisada ja eemaldada süsteemiikoone."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"olekuribana kuvamine"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 858b656d930c..07950b50d350 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Gailuaren hatz-marken sentsorean egindako keinuak atzeman ditzake."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Pantaila-argazkiak atera."</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pantaila-argazkiak atera ditzake."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Aurrebista, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desgaitu edo aldatu egoera-barra"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Egoera-barra desgaitzea edo sistema-ikonoak gehitzea edo kentzea baimentzen die aplikazioei."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"bihurtu egoera-barra"</string>
@@ -1862,8 +1861,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administratzaileak eguneratu du"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administratzaileak ezabatu du"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Ados"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Bateria-aurreztaileak gai iluna aktibatzen du, eta murriztu edo desaktibatu egiten ditu atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk."</string>
- <string name="battery_saver_description" msgid="8518809702138617167">"Bateria-aurreztaileak gai iluna aktibatzen du, eta atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk murrizten edo desaktibatzen ditu."</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Bateria-aurreztaileak gai iluna aktibatzen du, eta atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk mugatzen edo desaktibatzen ditu."</string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Bateria-aurreztaileak gai iluna aktibatzen du, eta atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk mugatzen edo desaktibatzen ditu."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Datu-erabilera murrizteko, atzeko planoan datuak bidaltzea eta jasotzea galarazten die datu-aurreztaileak aplikazio batzuei. Erabiltzen ari zaren aplikazioek datuak atzitu ahalko dituzte, baina baliteke maiztasun txikiagoarekin atzitzea. Ondorioz, adibidez, baliteke irudiak ez erakustea haiek sakatu arte."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Datu-aurreztailea aktibatu nahi duzu?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Aktibatu"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 5b5d5e4b57b1..4e57f21efc94 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -297,7 +297,7 @@
<string name="safeMode" msgid="8974401416068943888">"حالت ایمن"</string>
<string name="android_system_label" msgid="5974767339591067210">"‏سیستم Android"</string>
<string name="user_owner_label" msgid="8628726904184471211">"جابه‌جا شدن به نمایه شخصی"</string>
- <string name="managed_profile_label" msgid="7316778766973512382">"جابه‌جا شدن به نمایه کاری"</string>
+ <string name="managed_profile_label" msgid="7316778766973512382">"رفتن به نمایه کاری"</string>
<string name="permgrouplab_contacts" msgid="4254143639307316920">"مخاطبین"</string>
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"دسترسی به مخاطبین شما"</string>
<string name="permgrouplab_location" msgid="1858277002233964394">"مکان"</string>
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"می‌تواند اشاره‌های اجرا‌شده روی حسگر اثرانگشت دستگاه را ثبت کند."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"گرفتن نماگرفت"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"می‌تواند از نمایشگر نماگرفت بگیرد."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"پیش‌نما، <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"غیرفعال کردن یا تغییر نوار وضعیت"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"‏به برنامه اجازه می‎دهد تا نوار وضعیت را غیرفعال کند یا نمادهای سیستم را اضافه یا حذف کند."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"نوار وضعیت باشد"</string>
@@ -596,7 +595,7 @@
<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>
- <string name="fingerprint_acquired_power_press" msgid="3107864151278434961">"فشردن دکمه روشن/ خاموش شناسایی شد"</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-array name="fingerprint_acquired_vendor">
@@ -618,7 +617,7 @@
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"این دستگاه حسگر اثر انگشت ندارد."</string>
<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_error_power_pressed" msgid="5479524500542129414">"دکمه روشن/خاموش فشار داده شد"</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>
@@ -1253,11 +1252,11 @@
<string name="android_preparing_apk" msgid="589736917792300956">"آماده‌سازی <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"درحال آغاز کردن برنامه‌ها."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"درحال اتمام راه‌اندازی."</string>
- <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"دکمه روشن/ خاموش را فشار دادید — این کار معمولاً صفحه‌نمایش را خاموش می‌کند.\n\nهنگام راه‌اندازی اثر انگشت، آرام ضربه بزنید."</string>
+ <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"دکمه روشن/خاموش را فشار دادید — این کار معمولاً صفحه‌نمایش را خاموش می‌کند.\n\nهنگام راه‌اندازی اثر انگشت، آرام ضربه بزنید."</string>
<string name="fp_power_button_enrollment_title" msgid="6976841690455338563">"برای اتمام راه‌اندازی، صفحه را خاموش کنید"</string>
<string name="fp_power_button_enrollment_button_text" msgid="3199783266386029200">"خاموش کردن"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"تأیید اثر انگشت را ادامه می‌دهید؟"</string>
- <string name="fp_power_button_bp_message" msgid="2983163038168903393">"دکمه روشن/ خاموش را فشار دادید — این کار معمولاً صفحه‌نمایش را خاموش می‌کند.\n\nبرای تأیید اثر انگشتتان، آرام ضربه بزنید."</string>
+ <string name="fp_power_button_bp_message" msgid="2983163038168903393">"دکمه روشن/خاموش را فشار دادید — این کار معمولاً صفحه‌نمایش را خاموش می‌کند.\n\nبرای تأیید اثر انگشتتان، آرام ضربه بزنید."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"خاموش کردن صفحه"</string>
<string name="fp_power_button_bp_negative_button" msgid="3971364246496775178">"ادامه"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> در حال اجرا"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index e2b8fcc8dde7..207f397499b1 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Voi tallentaa laitteen sormenjälkitunnistimelle tehtyjä eleitä."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ota kuvakaappaus"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Voi ottaa kuvakaappauksen näytöstä."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Esikatselu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"poista tilapalkki käytöstä tai muokkaa tilapalkkia"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Antaa sovelluksen poistaa tilapalkin käytöstä ja lisätä tai poistaa järjestelmäkuvakkeita."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"sijaita tilapalkissa"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 3e29326d91eb..257db1c25514 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Peut capturer des gestes effectués sur le capteur d\'empreintes digitales de l\'appareil."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Prendre une capture d\'écran"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Peut prendre une capture de l\'écran."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Aperçu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"désactiver ou modifier la barre d\'état"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"servir de barre d\'état"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index c5bf6a945775..01f8f08d9740 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Peut enregistrer des gestes effectués sur le lecteur d\'empreinte digitale de l\'appareil."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Prendre une capture d\'écran"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Peut prendre des captures d\'écran."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Aperçu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"Désactivation ou modification de la barre d\'état"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"remplacer la barre d\'état"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index b89bd3f0c40e..e464da38b8d1 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode rexistrar os xestos realizados no sensor de impresión dixital do dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Facer captura de pantalla"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode facer capturas de pantalla."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desactivar ou modificar a barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite á aplicación desactivar a barra de estado ou engadir e quitar as iconas do sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"actuar como a barra de estado"</string>
@@ -1326,8 +1325,8 @@
<string name="sms_control_yes" msgid="4858845109269524622">"Permitir"</string>
<string name="sms_control_no" msgid="4845717880040355570">"Rexeitar"</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; quere enviar unha mensaxe a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
- <string name="sms_short_code_details" msgid="2723725738333388351">"Esta acción "<b>"pode supoñer custos"</b>" na túa conta de teléfono móbil."</string>
- <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Esta acción suporá custos na túa conta de teléfono móbil."</b></string>
+ <string name="sms_short_code_details" msgid="2723725738333388351">"Esta acción "<b>"pode supoñer custos"</b>" na conta do teu operador móbil."</string>
+ <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Esta acción suporá custos na conta do teu operador móbil."</b></string>
<string name="sms_short_code_confirm_allow" msgid="920477594325526691">"Enviar"</string>
<string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"Cancelar"</string>
<string name="sms_short_code_remember_choice" msgid="1374526438647744862">"Lembrar a miña opción"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index c77502178ac7..3c96016970b1 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ડિવાઇસના ફિંગરપ્રિન્ટ સેન્સર પર કરવામાં આવેલા સંકેતો કૅપ્ચર કરી શકે છે."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"સ્ક્રીનશૉટ લો"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ડિસ્પ્લેનો સ્ક્રીનશૉટ લઈ શકે છે."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"પ્રીવ્યૂ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"સ્ટેટસ બારને અક્ષમ કરો અથવા તેમાં ફેરફાર કરો"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ઍપ્લિકેશનને સ્ટેટસ બાર અક્ષમ કરવાની અથવા સિસ્ટમ આયકન્સ ઉમેરવા અને દૂર કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"સ્ટેટસ બારમાં બતાવો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 1951a38804e9..a20714d528be 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"डिवाइस के फ़िंगरप्रिंट सेंसर पर किए गए हाथ के जेस्चर कैप्चर किए जा सकते हैं."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट लें"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिसप्ले का स्क्रीनशॉट लिया जा सकता है."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> की झलक"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार को अक्षम करें या बदलें"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ऐप को, स्टेटस बार को बंद करने या सिस्‍टम आइकॉन को जोड़ने और निकालने की अनुमति देता है."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार को रहने दें"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 3d98bb4d79f0..d3c252a2e0c5 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Érzékeli az eszköz ujjlenyomat-érzékelőjén végzett kézmozdulatokat."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Képernyőkép készítése"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Készíthet képernyőképet a kijelzőről."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Előnézet, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"állapotsor kikapcsolása vagy módosítása"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Lehetővé teszi az alkalmazás számára az állapotsor kikapcsolását, illetve rendszerikonok hozzáadását és eltávolítását."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"az állapotsor szerepének átvétele"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 5d60c5dd1d35..8392df33c19f 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Կարող է արձանագրել մատնահետքերի սկաների վրա կատարվող ժեստերը"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Սքրինշոթի ստեղծում"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Կարող է ստեղծել էկրանի սքրինշոթ։"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Նախադիտում, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"անջատել կամ փոփոխել կարգավիճակի գոտին"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Թույլ է տալիս հավելվածին անջատել կարգավիճակի գոտին կամ ավելացնել ու հեռացնել համակարգի պատկերակները:"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"լինել կարգավիճակի գոտի"</string>
@@ -1948,7 +1947,7 @@
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>՝ անհասանելի է"</string>
<string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Անհրաժեշտ է թույլտվություն"</string>
<string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Տեսախցիկն անհասանելի է"</string>
- <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Շարունակեք հեռախոսով"</string>
+ <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Շարու­նակեք հեռախոսով"</string>
<string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Խոսափողն անհասանելի է"</string>
<string name="app_streaming_blocked_title_for_playstore_dialog" msgid="8149823099822897538">"Play Խանութը հասանելի չէ"</string>
<string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-ի կարգավորումներն անհասանելի են"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 2173eb9364e0..9257ed4cd375 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dapat merekam gestur yang dilakukan di sensor sidik jari perangkat."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Dapat mengambil screenshot tampilan."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Pratinjau, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"nonaktifkan atau ubah bilah status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Mengizinkan apl menonaktifkan bilah status atau menambah dan menghapus ikon sistem."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"jadikan bilah status"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index d9df6203143c..30eefdf8ee59 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Getur fangað bendingar sem eru gerðar á fingrafaralesara tækisins."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Taka skjámynd"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Getur tekið skjámynd af skjánum."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Forskoðun, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"slökkva á eða breyta stöðustiku"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Leyfir forriti að slökkva á stöðustikunni eða bæta við og fjarlægja kerfistákn."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vera stöðustikan"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index dd1b8defba37..1520d1727314 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -298,7 +298,7 @@
<string name="safeMode" msgid="8974401416068943888">"Modalità provvisoria"</string>
<string name="android_system_label" msgid="5974767339591067210">"Sistema Android"</string>
<string name="user_owner_label" msgid="8628726904184471211">"Passa al profilo personale"</string>
- <string name="managed_profile_label" msgid="7316778766973512382">"Passa a profilo di lavoro"</string>
+ <string name="managed_profile_label" msgid="7316778766973512382">"Passa al profilo di lavoro"</string>
<string name="permgrouplab_contacts" msgid="4254143639307316920">"Contatti"</string>
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"Possono accedere ai contatti"</string>
<string name="permgrouplab_location" msgid="1858277002233964394">"Posizione"</string>
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"È in grado di rilevare i gesti compiuti con il sensore di impronte dei dispositivi."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Acquisire screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Può acquisire uno screenshot del display."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> in anteprima"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disattivazione o modifica della barra di stato"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ruolo di barra di stato"</string>
@@ -1973,7 +1972,7 @@
<string name="profile_encrypted_message" msgid="1128512616293157802">"Tocca per sbloc. prof. di lav."</string>
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connesso a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tocca per visualizzare i file"</string>
- <string name="pin_target" msgid="8036028973110156895">"Blocca"</string>
+ <string name="pin_target" msgid="8036028973110156895">"Fissa"</string>
<string name="pin_specific_target" msgid="7824671240625957415">"Blocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Sgancia"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"Sblocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
@@ -2056,8 +2055,8 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Consentire all\'app <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> di accedere a tutti i log del dispositivo?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Consenti accesso una tantum"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Non consentire"</string>
- <string name="log_access_confirmation_body" product="default" msgid="1806692062668620735">"I log del dispositivo registrano tutto ciò che succede sul tuo dispositivo. Le app possono usare questi log per individuare problemi e correggerli.\n\nAlcuni log potrebbero contenere informazioni sensibili, quindi concedi l\'accesso a tutti i log del dispositivo soltanto alle app attendibili. \n\nSe le neghi l\'accesso a tutti i log del dispositivo, questa app può comunque accedere ai propri log. Il produttore del tuo dispositivo potrebbe essere comunque in grado di accedere ad alcuni log o informazioni sul dispositivo."</string>
- <string name="log_access_confirmation_body" product="tv" msgid="7379536536425265262">"I log del dispositivo registrano tutto ciò che succede sul tuo dispositivo. Le app possono usare questi log per individuare problemi e correggerli.\n\nAlcuni log potrebbero contenere informazioni sensibili, quindi concedi l\'accesso a tutti i log del dispositivo soltanto alle app attendibili. \n\nSe le neghi l\'accesso a tutti i log del dispositivo, questa app può comunque accedere ai propri log. Il produttore del tuo dispositivo potrebbe essere comunque in grado di accedere ad alcuni log o informazioni sul dispositivo.\n\nScopri di più all\'indirizzo g.co/android/devicelogs."</string>
+ <string name="log_access_confirmation_body" product="default" msgid="1806692062668620735">"I log del dispositivo registrano tutto ciò che succede sul tuo dispositivo. Le app possono usare questi log per individuare problemi e correggerli.\n\nAlcuni log potrebbero contenere informazioni sensibili, quindi concedi l\'accesso a tutti i log del dispositivo soltanto alle app attendibili. \n\nSe neghi l\'accesso a tutti i log del dispositivo, questa app può comunque accedere ai propri log. Il produttore del tuo dispositivo potrebbe essere comunque in grado di accedere ad alcuni log o informazioni sul dispositivo."</string>
+ <string name="log_access_confirmation_body" product="tv" msgid="7379536536425265262">"I log del dispositivo registrano tutto ciò che succede sul tuo dispositivo. Le app possono usare questi log per individuare problemi e correggerli.\n\nAlcuni log potrebbero contenere informazioni sensibili, quindi concedi l\'accesso a tutti i log del dispositivo soltanto alle app attendibili. \n\nSe neghi l\'accesso a tutti i log del dispositivo, questa app può comunque accedere ai propri log. Il produttore del tuo dispositivo potrebbe essere comunque in grado di accedere ad alcuni log o informazioni sul dispositivo.\n\nScopri di più all\'indirizzo g.co/android/devicelogs."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Non mostrare più"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"L\'app <xliff:g id="APP_0">%1$s</xliff:g> vuole mostrare porzioni dell\'app <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Modifica"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a6c46a21f585..628adec67e2a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"אפשרות לזהות תנועות בזמן נגיעה בחיישן טביעות האצבע של המכשיר."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"צילום המסך"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ניתן לצלם צילום מסך של התצוגה."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"תצוגה מקדימה, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"השבתה או שינוי של שורת הסטטוס"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"מאפשרת לאפליקציה להשבית את שורת הסטטוס או להוסיף ולהסיר סמלי מערכת."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"להיות שורת הסטטוס"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 1879cc62088b..5a3deed68609 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"デバイスの指紋認証センサーで行われた操作をキャプチャできます。"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"スクリーンショットの撮影"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ディスプレイのスクリーンショットを撮影できます。"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"プレビュー - <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ステータスバーの無効化や変更"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ステータスバーの無効化、システムアイコンの追加や削除をアプリに許可します。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ステータスバーへの表示"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 8343198bc157..67c82033d3e1 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"შეუძლია აღბეჭდოს მოწყობილობის თითის ანაბეჭდის სენსორზე განხორციელებული ჟესტები."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ეკრანის ანაბეჭდის გადაღება"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"შეუძლია ეკრანის ანაბეჭდის გადაღება."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"გადახედვა, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"სტატუსის ზოლის გათიშვა ან ცვლილება"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"აპს შეეძლება სტატუსების ზოლის გათიშვა და სისტემის ხატულების დამატება/წაშლა."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"სტატუსის ზოლის ჩანაცვლება"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index c863cd8d2cae..6bfce9e07f9d 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Құрылғының саусақ ізі сенсорында орындалған қимылдарды сақтайды."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот жасау"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдің скриншотын жасай аласыз."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Алғы көрініс, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"күйін көрсету тақтасын өшіру немесе өзгерту"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Қолданбаға күй жолағын өшіруге немесе жүйелік белгішелерді қосуға және жоюға рұқсат береді."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"күй жолағы болу"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 35b59bef94a3..445020d7d785 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"អាចចាប់យក​ចលនា​ដែលធ្វើនៅលើ​នៅលើ​ឧបករណ៍​ចាប់​ស្នាម​ម្រាមដៃ​របស់ឧបករណ៍បាន។"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ថត​អេក្រង់"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"អាច​ថត​អេក្រង់​នៃ​ផ្ទាំង​អេក្រង់​បាន។"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"មើល​សាកល្បង <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"បិទ ឬ​កែ​របារ​ស្ថានភាព"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ឲ្យ​កម្មវិធី​បិទ​របារ​ស្ថានភាព ឬ​បន្ថែម និង​លុប​រូប​តំណាង​ប្រព័ន្ធ។"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ធ្វើជារបារស្ថានភាព"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index d0decdf7d983..ee76ca3d0c40 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ಸಾಧನದ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌ನಲ್ಲಿ ನಡೆಸಿದ ಗೆಶ್ಚರ್‌ಗಳನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಿ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ಪ್ರದರ್ಶನದ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ತೆಗೆದುಕೊಳ್ಳಬಲ್ಲದು."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"ಪೂರ್ವವೀಕ್ಷಣೆ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 04dc86a6c9a7..bbfe13488f39 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"기기 지문 센서에서 동작을 캡처합니다."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"스크린샷 촬영"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"디스플레이 스크린샷을 촬영할 수 있습니다."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"미리보기, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"상태 표시줄 사용 중지 또는 수정"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"앱이 상태 표시줄을 사용중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 허용합니다."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"상태 표시줄에 위치"</string>
@@ -2052,10 +2051,10 @@
<string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"제거"</string>
<string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"열기"</string>
<string name="harmful_app_warning_title" msgid="8794823880881113856">"유해한 앱 감지됨"</string>
- <string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>에서 모든 기기 로그에 액세스하도록 허용하시겠습니까?"</string>
+ <string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>에서 전체 기기 로그에 액세스하도록 허용하시겠습니까?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"일회성 액세스 허용"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"허용 안함"</string>
- <string name="log_access_confirmation_body" product="default" msgid="1806692062668620735">"기기 로그에 기기에서 발생한 상황이 기록됩니다. 앱은 문제를 찾고 해결하는 데 이 로그를 사용할 수 있습니다.\n\n일부 로그는 민감한 정보를 포함할 수 있으므로 신뢰할 수 있는 앱만 모든 기기 로그에 액세스하도록 허용하세요. \n\n앱에 전체 기기 로그에 대한 액세스 권한을 부여하지 않아도 앱이 자체 로그에는 액세스할 수 있습니다. 기기 제조업체에서 일부 로그 또는 기기 내 정보에 액세스할 수도 있습니다."</string>
+ <string name="log_access_confirmation_body" product="default" msgid="1806692062668620735">"기기 로그에는 기기에서 발생한 상황이 기록됩니다. 앱은 문제를 찾고 해결하는 데 이 로그를 사용할 수 있습니다.\n\n일부 로그는 민감한 정보를 포함할 수 있으므로 신뢰할 수 있는 앱만 전체 기기 로그에 액세스하도록 허용하세요. \n\n앱에 전체 기기 로그에 대한 액세스 권한을 부여하지 않아도 앱이 자체 로그에는 액세스할 수 있습니다. 기기 제조업체에서 일부 로그 또는 기기 내 정보에 액세스할 수도 있습니다."</string>
<string name="log_access_confirmation_body" product="tv" msgid="7379536536425265262">"기기 로그에는 기기에서 발생한 상황이 기록됩니다. 앱은 문제를 찾고 해결하는 데 이 로그를 사용할 수 있습니다.\n\n일부 로그에 민감한 정보가 포함될 수 있으므로 신뢰할 수 있는 앱만 모든 기기 로그에 액세스하도록 허용하세요. \n\n앱에 전체 기기 로그에 대한 액세스 권한을 부여하지 않아도, 앱이 자체 로그에는 액세스할 수 있습니다. 기기 제조업체에서 기기 내 일부 로그 또는 정보에 액세스할 수도 있습니다.\n\ng.co/android/devicelogs에서 자세히 알아보세요."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"다시 표시 안함"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g>에서 <xliff:g id="APP_2">%2$s</xliff:g>의 슬라이스를 표시하려고 합니다"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index bdb8fe1576a1..100a5631f0b2 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Түзмөктөгү манжа изинин сенсорунда жасалган жаңсоолорду жаздырып алат."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот тартып алуу"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдин скриншотун тартып алсаңыз болот."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Алдын ала көрүү, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"абал тилкесин өчүрүү же өзгөртүү"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Колдонмого абал тилкесин өчүрүү же тутум сүрөтчөлөрүн кошуу же алып салуу мүмкүнчүлүгүн берет."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"абал тилкесинин милдетин аткаруу"</string>
@@ -1417,7 +1416,7 @@
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Түзмөктү форматташыңыз керек болушу мүмкүн. Чыгаруу үчүн таптап коюңуз."</string>
<string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> аныкталды"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> иштебей жатат"</string>
- <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Тууралоо үчүн таптаңыз."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Орнотуу үчүн басыңыз."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Колдоого алынуучу форматта орнотуу үчүн <xliff:g id="NAME">%s</xliff:g> тандаңыз."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Түзмөктү форматташыңыз керек болушу мүмкүн"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> күтүүсүздөн өчүрүлдү"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index b7a4c05a2f61..f06b2cf2ab2f 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ສາມາດບັນທຶກທ່າທາງທີ່ເກີດຂຶ້ນໃນອຸປະກອນເຊັນເຊີລາຍນິ້ວມືໄດ້."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ຖ່າຍຮູບໜ້າຈໍ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"ຕົວຢ່າງ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ປິດການນນຳໃຊ້ ຫຼື ແກ້ໄຂແຖບສະຖານະ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງແຖບສະຖານະ ຫຼືເພີ່ມ ແລະລຶບໄອຄອນລະບົບອອກໄດ້."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ເປັນ​ແຖບ​ສະ​ຖາ​ນະ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index cdfa1ac3cc5e..fcc0918ea9d2 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -344,8 +344,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Gali užfiksuoti gestus, atliktus naudojant įrenginio piršto antspaudo jutiklį."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrano kopijos kūrimas"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Galima sukurti vaizdo ekrano kopiją."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Peržiūra, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"išjungti ar keisti būsenos juostą"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Leidžiama programai neleisti būsenos juostos arba pridėti ir pašalinti sistemos piktogramas."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"būti būsenos juosta"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 66826c9fa605..e1baffd39bca 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Var uztvert žestus ierīces pirksta nospieduma sensorā."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrānuzņēmuma izveide"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Var izveidot displeja ekrānuzņēmumu."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> (priekšskatījums)"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"atspējot vai pārveidot statusa joslu"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ļauj lietotnei atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"Būt par statusa joslu"</string>
diff --git a/core/res/res/values-mcc334-mnc020-th/strings.xml b/core/res/res/values-mcc334-mnc020-th/strings.xml
index e4e62f0a0417..dfd73abd82e4 100644
--- a/core/res/res/values-mcc334-mnc020-th/strings.xml
+++ b/core/res/res/values-mcc334-mnc020-th/strings.xml
@@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string>
- <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"การตรวจสอบสิทธิ์ล้มเหลว -29-"</string>
+ <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"การตรวจสอบสิทธิ์ไม่สำเร็จ -29-"</string>
<string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ไม่ได้สมัครใช้บริการ -33-"</string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ไม่อนุญาตการเชื่อมต่อ PDN หลายรายการสำหรับ APN ที่กำหนด -55-"</string>
</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index dd5e44ed3709..605b7bba643a 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да сними движења што се направени на сензорот за отпечатоци на уредот."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Зачувување слика од екранот"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да зачува слика од екранот."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Преглед, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"оневозможи или измени статусна лента"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволува апликацијата да ја оневозможи статусната лента или да додава или отстранува системски икони."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"да стане статусна лента"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 4ed058dfb073..7a9d4dab7c54 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ഉപകരണത്തിന്റെ ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെയ്‌ത ജെസ്‌റ്ററുകൾ ക്യാപ്‌ചർ ചെയ്യാനാകും."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"സ്ക്രീന്‍ഷോട്ട് എടുക്കുക"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ഡിസ്‌പ്ലേയുടെ സ്‌ക്രീൻഷോട്ട് എടുക്കാൻ കഴിയും."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"പ്രിവ്യൂ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്‌ക്കരിക്കുക"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്‌റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 5b8209ba92f2..e4c68e2f41ed 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Төхөөрөмжийн хурууны хээ мэдрэгчид зангасан зангааг танина."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Дэлгэцийн зургийг дарах"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дэлгэцийн зургийг дарах боломжтой."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Урьдчилан үзэх, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"статус самбарыг идэвхгүй болгох болон өөрчлөх"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Апп нь статус самбарыг идэвхгүй болгох эсвэл систем дүрсийг нэмэх, хасах боломжтой."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"статусын хэсэг болох"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index ee6e2eedffd5..1e08228b4fac 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"डिव्‍हाइसच्‍या फिंगरप्रिंट सेंन्सरवरील जेश्चर कॅप्‍चर करू शकते."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट घ्या"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेचा स्क्रीनशॉट घेऊ शकतो."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"पूर्वावलोकन, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार अक्षम करा किंवा सुधारित करा"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अ‍ॅप ला अनुमती देते."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार होऊ द्या"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 8f5476281f09..dca9de618071 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Boleh menangkap gerak isyarat yang dilakukan pada penderia cap jari peranti."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil tangkapan skrin"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Boleh mengambil tangkapan skrin paparan."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Pratonton, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"lumpuhkan atau ubah suai bar status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Membenarkan apl melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"jadi bar status"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 939df8038677..70d352f3a832 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"စက်ပစ္စည်း၏ လက်ဗွေအာရုံခံကိရိယာတွင် လုပ်ဆောင်ထားသည့် လက်ဟန်များကို မှတ်သားထားနိုင်သည်။"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ဖန်သားပြင်ဓာတ်ပုံ ရိုက်ရန်"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ဖန်သားပြင်ပြသမှုကို ဓာတ်ပုံရိုက်နိုင်ပါသည်။"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> အစမ်းကြည့်ခြင်း"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"အက်ပ်အား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"အခြေအနေပြ ဘားဖြစ်ပါစေ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index f0f4439c57aa..c9c277cf6a12 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan fange inn bevegelser som utføres på enhetens fingeravtrykkssensor."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skjermdump"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan ikke ta en skjermdump av skjermen."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Forhåndsvisning, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller endre statusfeltet"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Lar appen deaktivere statusfeltet eller legge til og fjerne systemikoner."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vise appen i statusfeltet"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 94551e5daad4..6e738671e1ba 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"यसले यन्त्रक‍ो फिंगरप्रिन्टसम्बन्धी सेन्सरमा गरिएका इसाराहरूलाई खिच्‍न सक्छ।"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रिनसट लिनुहोस्"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेको स्क्रिनसट लिन सकिन्छ।"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"प्रिभ्यू, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन एपलाई अनुमति दिन्छ।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"स्टाटस बार हुन दिनुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 0f7d35f3fb48..ba43d799f371 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan gebaren registreren die op de vingerafdruksensor van het apparaat worden getekend."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot maken"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan een screenshot van het scherm maken."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Voorbeeld, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"statusbalk uitzetten of wijzigen"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Hiermee kan de app de statusbalk uitzetten of systeemiconen toevoegen en verwijderen."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"de statusbalk zijn"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 26821da497b7..0ac3a3723ba7 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ଡିଭାଇସ୍‌ର ଟିପଚିହ୍ନ ସେନସର୍ ଉପରେ ଜେଶ୍ଚର୍‍ କ୍ୟାପଚର୍‍ କାର୍ଯ୍ୟ କରାଯାଇପାରିବ।"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ସ୍କ୍ରିନସଟ୍ ନିଅନ୍ତୁ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ଡିସପ୍ଲେର ଏକ ସ୍କ୍ରିନସଟ୍ ନିଆଯାଇପାରେ।"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"ପ୍ରିଭ୍ୟୁ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ଷ୍ଟାଟସ୍‌ ବାର୍‌କୁ ଅକ୍ଷମ କିମ୍ୱା ସଂଶୋଧନ କରନ୍ତୁ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ଆପ୍‍କୁ, ସ୍ଥିତି ବାର୍‍ ଅକ୍ଷମ କରିବାକୁ କିମ୍ବା ସିଷ୍ଟମ୍‍ ଆଇକନ୍‍ ଯୋଡ଼ିବା କିମ୍ବା ବାହାର କରିବାକୁ ଦେଇଥାଏ।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ଷ୍ଟାଟସ୍‍ ବାର୍‍ ରହିବାକୁ ଦିଅନ୍ତୁ"</string>
@@ -1862,7 +1861,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ଆପଣଙ୍କ ଆଡମିନ୍‌‌ ଅପଡେଟ୍‍ କରିଛନ୍ତି"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ଆପଣଙ୍କ ଆଡମିନ୍‌‌ ଡିଲିଟ୍‍ କରିଛନ୍ତି"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ଠିକ୍ ଅଛି"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ବ୍ୟାଟେରୀ ସେଭର୍ ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ ଏବଂ ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ, କିଛି ଭିଜୁଆଲ୍ ଇଫେକ୍ଟ, କିଛି ଫିଚର୍ ଏବଂ କିଛି ନେଟୱାର୍କ ସଂଯୋଗକୁ ସୀମିତ କିମ୍ବା ବନ୍ଦ କରେ।"</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ବେଟେରୀ ସେଭର ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ ଏବଂ ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ, କିଛି ଭିଜୁଆଲ ଇଫେକ୍ଟ, କିଛି ଫିଚର ଏବଂ କିଛି ନେଟୱାର୍କ ସଂଯୋଗକୁ ସୀମିତ କିମ୍ବା ବନ୍ଦ କରେ।"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"ବ୍ୟାଟେରୀ ସେଭର୍ ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ ଏବଂ ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ, କିଛି ଭିଜୁଆଲ୍ ଇଫେକ୍ଟ, କିଛି ଫିଚର୍ ଏବଂ କିଛି ନେଟୱାର୍କ ସଂଯୋଗକୁ ସୀମିତ କିମ୍ବା ବନ୍ଦ କରେ।"</string>
<string name="data_saver_description" msgid="4995164271550590517">"ଡାଟା ବ୍ୟବହାର କମ୍‍ କରିବାରେ ସାହାଯ୍ୟ କରିବାକୁ, ଡାଟା ସେଭର୍‍ ବ୍ୟାକ୍‌ଗ୍ରାଉଣ୍ଡରେ ଡାଟା ପଠାଇବା କିମ୍ବା ପ୍ରାପ୍ତ କରିବାକୁ କିଛି ଆପ୍‍କୁ ବାରଣ କରେ। ଆପଣ ବର୍ତ୍ତମାନ ବ୍ୟବହାର କରୁଥିବା ଆପ୍‍, ଡାଟା ଆକ୍ସେସ୍‍ କରିପାରେ, କିନ୍ତୁ ଏହା କମ୍‍ ଥର କରିପାରେ। ଏହାର ଅର୍ଥ ହୋଇପାରେ ଯେମିତି ଆପଣ ଇମେଜଗୁଡ଼ିକୁ ଟାପ୍‍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ସେଗୁଡ଼ିକ ଡିସପ୍ଲେ ହୁଏ ନାହିଁ।"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ଡାଟା ସେଭର୍‌ ଚାଲୁ କରିବେ?"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index c8c382b1a289..660d395babc8 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ਡੀਵਾਈਸਾਂ ਦੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ \'ਤੇ ਕੀਤੇ ਗਏ ਸੰਕੇਤਾਂ ਨੂੰ ਕੈਪਚਰ ਕਰ ਸਕਦੇ ਹਨ।"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਓ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ਡਿਸਪਲੇ ਦਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈ ਸਕਦੀ ਹੈ।"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"ਪੂਰਵ-ਝਲਕ ਦੇਖੋ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ਸਥਿਤੀ ਪੱਟੀ ਬੰਦ ਕਰੋ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਪੱਟੀ ਨੂੰ ਚਾਲੂ ਕਰਨ ਜਾਂ ਸਿਸਟਮ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 8425a7a8a816..524f0448b262 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -344,8 +344,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Może przechwytywać gesty wykonywane na czytniku linii papilarnych w urządzeniu."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Robienie zrzutu ekranu"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Może robić zrzuty ekranu wyświetlacza."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Podgląd, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"wyłączanie lub zmienianie paska stanu"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"działanie jako pasek stanu"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 4fe36de666b9..f22499ad5d7f 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index b6fbbea10084..8ddf065ef798 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -561,7 +561,7 @@
<string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"Permite que a app aprenda o nível de complexidade do bloqueio de ecrã (elevado, médio, baixo ou nenhum), que indica o intervalo de comprimento e o tipo de bloqueio de ecrã possíveis. A app também pode sugerir aos utilizadores que atualizem o bloqueio de ecrã para um determinado nível, mas estes podem ignorar livremente a sugestão e continuar a navegação. Tenha em atenção que o bloqueio de ecrã não é armazenado em texto simples, pelo que a app desconhece a palavra-passe exata."</string>
<string name="permlab_postNotification" msgid="4875401198597803658">"mostrar notificações"</string>
<string name="permdesc_postNotification" msgid="5974977162462877075">"Permite à app mostrar notificações"</string>
- <string name="permlab_useBiometric" msgid="6314741124749633786">"Utilizar hardware biométrico"</string>
+ <string name="permlab_useBiometric" msgid="6314741124749633786">"Usar hardware biométrico"</string>
<string name="permdesc_useBiometric" msgid="7502858732677143410">"Permite que a app utilize hardware biométrico para autenticação."</string>
<string name="permlab_manageFingerprint" msgid="7432667156322821178">"gerir o hardware de impressão digital"</string>
<string name="permdesc_manageFingerprint" msgid="2025616816437339865">"Permite que a app invoque métodos para adicionar e eliminar modelos de impressão digital para utilização."</string>
@@ -575,8 +575,8 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Permite que a app modifique a sua coleção de fotos."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ler as localizações a partir da sua coleção de multimédia"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Permite que a app leia as localizações a partir da sua coleção de multimédia."</string>
- <string name="biometric_app_setting_name" msgid="3339209978734534457">"Utilizar a biometria"</string>
- <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Utilizar a biometria ou o bloqueio de ecrã"</string>
+ <string name="biometric_app_setting_name" msgid="3339209978734534457">"Usar a biometria"</string>
+ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar a biometria ou o bloqueio de ecrã"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirme a sua identidade"</string>
<string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Utilize a biometria para continuar."</string>
<string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Utilize a biometria ou o bloqueio de ecrã para continuar"</string>
@@ -586,7 +586,7 @@
<string name="biometric_error_canceled" msgid="8266582404844179778">"Autenticação cancelada"</string>
<string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nenhum PIN, padrão ou palavra-passe definidos."</string>
<string name="biometric_error_generic" msgid="6784371929985434439">"Erro ao autenticar."</string>
- <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utilizar o bloqueio de ecrã"</string>
+ <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>
@@ -620,8 +620,8 @@
<string name="fingerprint_error_bad_calibration" msgid="4385512597740168120">"Não é possível usar o sensor de impressões digitais. Visite um fornecedor de serviços de reparação"</string>
<string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Botão ligar/desligar premido"</string>
<string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
- <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Utilizar a impressão digital"</string>
- <string name="fingerprint_or_screen_lock_app_setting_name" msgid="3501743523487644907">"Utilizar o bloqueio de ecrã ou a impressão digital"</string>
+ <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Usar a impressão digital"</string>
+ <string name="fingerprint_or_screen_lock_app_setting_name" msgid="3501743523487644907">"Usar o bloqueio de ecrã ou a impressão digital"</string>
<string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Utilize a sua impressão digital para continuar."</string>
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilize a impressão digital ou o bloqueio de ecrã para continuar"</string>
<string-array name="fingerprint_error_vendor">
@@ -681,8 +681,8 @@
<string name="face_error_hw_not_present" msgid="7940978724978763011">"O Desbloqueio facial não é suportado neste dispositivo"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensor temporariamente desativado."</string>
<string name="face_name_template" msgid="3877037340223318119">"Rosto <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="5854024256907828015">"Utilizar o Desbloqueio facial"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Utilizar o bloqueio através do rosto ou de ecrã"</string>
+ <string name="face_app_setting_name" msgid="5854024256907828015">"Usar o Desbloqueio facial"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usar o bloqueio através do rosto ou de ecrã"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Utilize o rosto para continuar"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilize o rosto ou o bloqueio de ecrã para continuar"</string>
<string-array name="face_error_vendor">
@@ -1196,13 +1196,13 @@
<string name="whichSendToApplicationNamed" msgid="3385686512014670003">"Enviar com %1$s"</string>
<string name="whichSendToApplicationLabel" msgid="3543240188816513303">"Enviar"</string>
<string name="whichHomeApplication" msgid="8276350727038396616">"Selecione uma app Página inicial"</string>
- <string name="whichHomeApplicationNamed" msgid="5855990024847433794">"Utilizar %1$s como Página inicial"</string>
+ <string name="whichHomeApplicationNamed" msgid="5855990024847433794">"Usar %1$s como Página inicial"</string>
<string name="whichHomeApplicationLabel" msgid="8907334282202933959">"Capturar imagem"</string>
<string name="whichImageCaptureApplication" msgid="2737413019463215284">"Capturar imagem com"</string>
<string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"Capturar imagem com o %1$s"</string>
<string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"Capturar imagem"</string>
- <string name="alwaysUse" msgid="3153558199076112903">"Utilizar por predefinição para esta ação."</string>
- <string name="use_a_different_app" msgid="4987790276170972776">"Utilizar outra app"</string>
+ <string name="alwaysUse" msgid="3153558199076112903">"Usar por predefinição para esta ação."</string>
+ <string name="use_a_different_app" msgid="4987790276170972776">"Usar outra app"</string>
<string name="clearDefaultHintMsg" msgid="1325866337702524936">"Limpar a predefinição nas Definições do Sistema &gt; Apps &gt; Transferidas."</string>
<string name="chooseActivity" msgid="8563390197659779956">"Escolha uma ação"</string>
<string name="chooseUsbActivity" msgid="2096269989990986612">"Escolher uma app para o dispositivo USB"</string>
@@ -1704,7 +1704,7 @@
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desativar atalho"</string>
- <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atalho"</string>
+ <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correção da cor"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo para uma mão"</string>
@@ -2160,8 +2160,8 @@
<string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Sem apps pessoais"</string>
<string name="miniresolver_open_in_personal" msgid="3874522693661065566">"Abrir a app <xliff:g id="APP">%s</xliff:g> no seu perfil pessoal?"</string>
<string name="miniresolver_open_in_work" msgid="4415223793669536559">"Abrir a app <xliff:g id="APP">%s</xliff:g> no seu perfil de trabalho?"</string>
- <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utilizar navegador pessoal"</string>
- <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utilizar navegador de trabalho"</string>
+ <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar navegador pessoal"</string>
+ <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar navegador de trabalho"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN para desbloqueio de rede do cartão SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN para desbloqueio do subconjunto da rede do cartão SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN para desbloqueio empresarial do cartão SIM"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 4fe36de666b9..f22499ad5d7f 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index a3be67382471..295187b13a57 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Poate reda gesturile făcute pe senzorul de amprentă al dispozitivului."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fă o captură de ecran"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Poate face o captură de ecran."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Previzualizare, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"dezactivare sau modificare bare de stare"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite aplicației să dezactiveze bara de stare sau să adauge și să elimine pictograme de sistem."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"să fie bara de stare"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index d5067ae4e035..f44910bc9b37 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -344,8 +344,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Использовать сканер отпечатков пальцев для дополнительных жестов."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Создавать скриншоты"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Создавать снимки экрана."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g>: предпросмотр"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"Отключение/изменение строки состояния"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"Замена строки состояния"</string>
@@ -1170,8 +1169,8 @@
<string name="no" msgid="5122037903299899715">"Отмена"</string>
<string name="dialog_alert_title" msgid="651856561974090712">"Внимание!"</string>
<string name="loading" msgid="3138021523725055037">"Загрузка…"</string>
- <string name="capital_on" msgid="2770685323900821829">"I"</string>
- <string name="capital_off" msgid="7443704171014626777">"O"</string>
+ <string name="capital_on" msgid="2770685323900821829">"Включено"</string>
+ <string name="capital_off" msgid="7443704171014626777">"Выключено"</string>
<string name="checked" msgid="9179896827054513119">"отмечено"</string>
<string name="not_checked" msgid="7972320087569023342">"не отмечено"</string>
<string name="selected" msgid="6614607926197755875">"выбрано"</string>
@@ -1864,8 +1863,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Обновлено администратором"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Удалено администратором"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, а также некоторые визуальные эффекты, функции и сетевые подключения."</string>
- <string name="battery_saver_description" msgid="8518809702138617167">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, а также некоторые визуальные эффекты, функции и сетевые подключения."</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, а также некоторые визуальные эффекты, часть функций и сетевых подключений."</string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, а также некоторые визуальные эффекты, часть функций и сетевых подключений."</string>
<string name="data_saver_description" msgid="4995164271550590517">"В режиме экономии трафика фоновая передача данных для некоторых приложений отключена. Приложение, которым вы пользуетесь, может получать и отправлять данные, но реже, чем обычно. Например, изображения могут не загружаться, пока вы не нажмете на них."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Включить экономию трафика?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Включить"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 66b0cd6fff3b..5896d91e8f72 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"උපාංගයෙහි ඇඟිලි සලකුණු සංවේදකය මත සිදු කරන ඉංගිත ග්‍රහණය කළ හැකිය."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"තිර රුව ගන්න"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"සංදර්ශකයේ තිර රුවක් ගැනීමට හැකිය."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"පෙරදසුන, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"තත්ව තීරුව අබල කරන්න හෝ වෙනස් කරන්න"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"තත්ව තීරුව අක්‍රිය කිරීමට හෝ පද්ධති නිරූපක එකතු හෝ ඉවත් කිරීමට යෙදුමට අවසර දේ."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"තත්ත්ව තීරුව බවට පත්වීම"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 816feefb8b7a..c1fe87f7cfe9 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -344,8 +344,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dokáže zaznamenať gestá na senzore odtlačkov prstov zariadenia."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Vytvoriť snímku obrazovky"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Je možné vytvoriť snímku obrazovky."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Ukážka, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"zakázanie alebo zmeny stavového riadka"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vydávanie sa za stavový riadok"</string>
@@ -1368,7 +1367,7 @@
<string name="usb_power_notification_message" msgid="7284765627437897702">"Pripojené zariadenie sa nabíja. Ďalšie možností získate klepnutím."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Bolo zistené analógové zvukové príslušenstvo"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Pripojené zariadenie nie je kompatibilné s týmto telefónom. Ďalšie informácie zobrazíte klepnutím."</string>
- <string name="adb_active_notification_title" msgid="408390247354560331">"Ladenie cez USB pripojené"</string>
+ <string name="adb_active_notification_title" msgid="408390247354560331">"Ladenie cez USB je pripojené"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"Klepnutím vypnite ladenie cez USB"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Vyberte, ak chcete zakázať ladenie cez USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Bezdrôtové ladenie je pripojené"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 61f2b51f3d85..9279cd67fc4d 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -344,8 +344,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Prepoznava poteze, narejene po tipalu prstnih odtisov naprave."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ustvarjanje posnetka zaslona"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Lahko naredi posnetek zaslona."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Predogled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"onemogočanje ali spreminjanje vrstice stanja"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikacijam omogoča onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikon sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"postane vrstica stanja"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 1708904e40e5..b42d2edb8c2d 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Mund të regjistrojë gjestet e kryera në sensorin e gjurmës së gishtit të pajisjes."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Nxirr një pamje të ekranit"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Mund të nxjerrë një pamje e ekranit."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Versioni paraprak, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"çaktivizo ose modifiko shiritin e statusit"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Lejon aplikacionin të çaktivizojë shiritin e statusit dhe të heqë ikonat e sistemit."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"të bëhet shiriti i statusit"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index fb36169d3e33..986b4058370f 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -343,8 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да региструје покрете на сензору за отисак прста на уређају."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Направи снимак екрана"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да направи снимак екрана."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Преглед, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"онемогућавање или измена статусне траке"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дозвољава апликацији да онемогући статусну траку или да додаје и уклања системске иконе."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"функционисање као статусна трака"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 6c593df1ff34..de202421e600 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -300,7 +300,7 @@
<string name="managed_profile_label" msgid="7316778766973512382">"Byt till jobbprofilen"</string>
<string name="permgrouplab_contacts" msgid="4254143639307316920">"Kontakter"</string>
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"få tillgång till dina kontakter"</string>
- <string name="permgrouplab_location" msgid="1858277002233964394">"Plats"</string>
+ <string name="permgrouplab_location" msgid="1858277002233964394">"plats"</string>
<string name="permgroupdesc_location" msgid="1995955142118450685">"komma åt enhetens platsuppgifter"</string>
<string name="permgrouplab_calendar" msgid="6426860926123033230">"Kalender"</string>
<string name="permgroupdesc_calendar" msgid="6762751063361489379">"få tillgång till din kalender"</string>
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan registrera rörelser som utförs med hjälp av enhetens fingeravtryckssensor."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skärmbild"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan ta en skärmbild av skärmen."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Förhandsgranskar <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"inaktivera eller ändra statusfält"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Tillåter att appen inaktiverar statusfältet eller lägger till och tar bort systemikoner."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"visas i statusfältet"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 715c1c4f1b34..304534b38584 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Inaweza kurekodi ishara zinazotekelezwa kwenye kitambua alama ya kidole."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Piga picha ya skrini"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Inaweza kupiga picha ya skrini ya onyesho."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Onyesho la kukagua, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"zima au rekebisha mwambaa hali"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa aikoni za mfumo."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"kuwa sehemu ya arifa"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 2c8c532fefeb..a3f14204ba06 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"சாதனத்தின் கைரேகை சென்சார்மேல் செய்யப்படும் சைகைகளைக் கேப்ட்சர் செய்ய முடியும்."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ஸ்கிரீன்ஷாட்டை எடுக்கும்"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"டிஸ்ப்ளேவை ஸ்கிரீன்ஷாட் எடுக்க முடியும்."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"மாதிரிக்காட்சி, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"நிலைப் பட்டியை முடக்குதல் அல்லது மாற்றுதல்"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"நிலைப் பட்டியை முடக்க அல்லது முறைமையில் ஐகான்களைச் சேர்க்க மற்றும் அகற்ற ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"நிலைப் பட்டியில் இருக்கும்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index bc5380279ca3..f9880dbd946b 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"పరికర వేలిముద్ర సెన్సార్‌లో ఉపయోగించిన సంజ్ఞలను క్యాప్చర్ చేయవచ్చు."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"స్క్రీన్‌షాట్‌ను తీయండి"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"డిస్‌ప్లే యొక్క స్క్రీన్‌షాట్ తీసుకోవచ్చు."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"ప్రివ్యూ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"స్టేటస్‌ బార్‌ను డిజేబుల్ చేయడం లేదా మార్చడం"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"స్టేటస్‌ బార్‌ను డిజేబుల్ చేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"స్టేటస్‌ పట్టీగా ఉండటం"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index d12b209e3d5e..93fe817bb65e 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"สามารถจับท่าทางสัมผัสที่เกิดขึ้นบนเซ็นเซอร์ลายนิ้วมือของอุปกรณ์"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ถ่ายภาพหน้าจอ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ถ่ายภาพหน้าจอได้"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"ตัวอย่าง <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ปิดการใช้งานหรือแก้ไขแถบสถานะ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"อนุญาตให้แอปพลิเคชันปิดใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"เป็นแถบสถานะ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 4c9e38847f1f..a56df48a9a2a 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Makukunan ang mga galaw na ginawa sa sensor para sa fingerprint ng device."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Kumuha ng screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puwedeng kumuha ng screenshot ng display."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"i-disable o baguhin ang status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Pinapayagan ang app na i-disable ang status bar o magdagdag at mag-alis ng mga icon ng system."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"maging status bar"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 4e6c6c78234f..270023d6e68c 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Cihazın parmak izi sensörlerinde gerçekleştirilen hareketleri yakalayabilir."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran görüntüsü al"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran görüntüsü alınabilir."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Önizleme, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"durum çubuğunu devre dışı bırak veya değiştir"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"durum çubuğunda olma"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 28828e713be4..8eddb31b54f7 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -344,8 +344,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може фіксувати жести на сканері відбитків пальців."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Робити знімки екрана"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може робити знімки екрана."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> (попередній перегляд)"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"вимикати чи змін. рядок стану"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволяє програмі вимикати рядок стану чи додавати та видаляти піктограми системи."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"відображатися як рядок стану"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index d94ccc133442..f98fc6c10a6c 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"آلہ کے فنگر پرنٹ سینسر پر کیے گئے اشاروں کو کیپچر کر سکتا ہے۔"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"اسکرین شاٹ لیں"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ڈسپلے کا اسکرین شاٹ لیا جا سکتا ہے۔"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"پیش منظر، <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"اسٹیٹس بار کو غیر فعال یا اس میں ترمیم کریں"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ایپ کو اسٹیٹس بار غیر فعال کرنے یا سسٹم آئیکنز شامل کرنے اور ہٹانے کی اجازت دیتا ہے۔"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"بطور اسٹیٹس بار کام لیں"</string>
@@ -2052,11 +2051,11 @@
<string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"اَن انسٹال کریں"</string>
<string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"بہر صورت کھولیں"</string>
<string name="harmful_app_warning_title" msgid="8794823880881113856">"ضرر رساں ایپ کا پتہ چلا"</string>
- <string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> کو آلے کے تمام لاگز تک رسائی کی اجازت دیں؟"</string>
+ <string name="log_access_confirmation_title" msgid="2343578467290592708">"‫<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> کو آلے کے تمام لاگز تک رسائی کی اجازت دیں؟"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"یک وقتی رسائی کی اجازت دیں"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"اجازت نہ دیں"</string>
<string name="log_access_confirmation_body" product="default" msgid="1806692062668620735">"آپ کے آلے پر جو ہوتا ہے آلے کے لاگز اسے ریکارڈ کر لیتے ہیں۔ ایپس ان لاگز کا استعمال مسائل کو تلاش کرنے اور ان کو حل کرنے کے لیے کر سکتی ہیں۔\n\nکچھ لاگز میں حساس معلومات شامل ہو سکتی ہیں، اس لیے صرف اپنے بھروسے مند ایپس کو ہی آلے کے تمام لاگز تک رسائی کی اجازت دیں۔ \n\nاگر آپ اس ایپ کو آلے کے تمام لاگز تک رسائی کی اجازت نہیں دیتے ہیں تب بھی یہ اپنے لاگز تک رسائی حاصل کر سکتی ہے۔ آپ کے آلے کا مینوفیکچرر اب بھی آپ کے آلے پر کچھ لاگز یا معلومات تک رسائی حاصل کر سکتا ہے۔"</string>
- <string name="log_access_confirmation_body" product="tv" msgid="7379536536425265262">"‏آپ کے آلے پر جو ہوتا ہے آلے کے لاگز اسے ریکارڈ کر لیتے ہیں۔ ایپس ان لاگز کا استعمال مسائل کو تلاش کرنے اور ان کو حل کرنے کے لیے کر سکتی ہیں۔\n\nکچھ لاگز میں حساس معلومات شامل ہو سکتی ہیں، اس لیے صرف اپنی بھروسے مند ایپس کو ہی آلے کے تمام لاگز تک رسائی کی اجازت دیں۔ \n\nاگر آپ اس ایپ کو آلے کے تمام لاگز تک رسائی کی اجازت نہیں دیتے ہیں تب بھی یہ اپنے لاگز تک رسائی حاصل کر سکتی ہے۔ آپ کے آلے کا مینوفیکچرر اب بھی آپ کے آلے پر کچھ لاگز یا معلومات تک رسائی حاصل کر سکتا ہے۔\n\ng.co/android/devicelogs پر مزید جانیں۔"</string>
+ <string name="log_access_confirmation_body" product="tv" msgid="7379536536425265262">"‏آپ کے آلے پر جو ہوتا ہے آلے کے لاگز اسے ریکارڈ کر لیتے ہیں۔ ایپس ان لاگز کا استعمال مسائل کو تلاش کرنے اور ان کو حل کرنے کے لیے کر سکتی ہیں۔\n\nکچھ لاگز میں حساس معلومات شامل ہو سکتی ہیں، اس لیے صرف اپنی بھروسے مند ایپس کو ہی آلے کے تمام لاگز تک رسائی کی اجازت دیں۔ \n\nاگر آپ اس ایپ کو آلے کے تمام لاگز تک رسائی کی اجازت نہیں دیتے ہیں تب بھی یہ اپنے لاگز تک رسائی حاصل کر سکتی ہے۔ آپ کے آلے کا مینوفیکچرر اب بھی آپ کے آلے پر کچھ لاگز یا معلومات تک رسائی حاصل کر سکتا ہے۔\n\nمزید جاننے کیلئے g.co/android/devicelogs ملاحظہ کریں۔"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"دوبارہ نہ دکھائیں"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> <xliff:g id="APP_2">%2$s</xliff:g> کے سلائسز دکھانا چاہتی ہے"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"ترمیم کریں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 8db468bb8181..c328e6f846db 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Barmoq izi skanerida kiritilgan ishoralarni taniy oladi."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Skrinshot olish"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekrandan skrinshot olishi mumkin."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Razm solish, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"holat panelini o‘zgartirish yoki o‘chirish"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ilova holat panelini o‘chirib qo‘yishi hamda tizim ikonkalarini qo‘shishi yoki olib tashlashi mumkin."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"holat qatorida ko‘rinishi"</string>
@@ -2052,8 +2051,8 @@
<string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"O‘CHIRIB TASHLASH"</string>
<string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"BARIBIR OCHILSIN"</string>
<string name="harmful_app_warning_title" msgid="8794823880881113856">"Zararli ilova aniqlandi"</string>
- <string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ilovasining qurilmadagi barcha jurnallarga kirishiga ruxsat berilsinmi?"</string>
- <string name="log_access_confirmation_allow" msgid="5302517782599389507">"Bir matalik foydalanishga ruxsat berish"</string>
+ <string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> uchun qurilmadagi barcha jurnallarga kirish ruxsati berilsinmi?"</string>
+ <string name="log_access_confirmation_allow" msgid="5302517782599389507">"Bir martalik ruxsat berish"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Rad etish"</string>
<string name="log_access_confirmation_body" product="default" msgid="1806692062668620735">"Qurilma jurnaliga qurilma bilan yuz bergan hodisalar qaydlari yoziladi. Ilovalar bu jurnal qaydlari yordamida muammolarni topishi va bartaraf qilishi mumkin.\n\nAyrim jurnal qaydlarida maxfiy axborotlar yozilishi mumkin, shu sababli qurilmadagi barcha jurnal qaydlariga ruxsatni faqat ishonchli ilovalarga bering. \n\nBu ilovaga qurilmadagi barcha jurnal qaydlariga ruxsat berilmasa ham, u oʻzining jurnalini ocha oladi. Qurilma ishlab chiqaruvchisi ham ayrim jurnallar yoki qurilma haqidagi axborotlarni ocha oladi."</string>
<string name="log_access_confirmation_body" product="tv" msgid="7379536536425265262">"Qurilma jurnaliga qurilma bilan yuz bergan hodisalar qaydlari yoziladi. Ilovalar bu jurnal qaydlari yordamida muammolarni topishi va bartaraf qilishi mumkin.\n\nAyrim jurnal qaydlarida maxfiy axborotlar yozilishi mumkin, shu sababli qurilmadagi barcha jurnal qaydlariga ruxsatni faqat ishonchli ilovalarga bering. \n\nBu ilovaga qurilmadagi barcha jurnal qaydlariga ruxsat berilmasa ham, u oʻzining jurnalini ocha oladi. Qurilma ishlab chiqaruvchisi ham ayrim jurnallar yoki qurilma haqidagi axborotlarni ocha oladi.\n\nBatafsil: g.co/android/devicelogs."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 30cab1ae2c11..c71a33d44b4a 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Có thể ghi lại các cử chỉ được thực hiện trên cảm biến vân tay của thiết bị."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Chụp ảnh màn hình"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Có thể chụp ảnh màn hình."</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Bản xem trước, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"trở thành thanh trạng thái"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 3a8ab3cab7fa..5e11f1934b5a 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以捕捉在设备指纹传感器上执行的手势。"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"截取屏幕截图"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可截取显示画面的屏幕截图。"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"预览,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改状态栏"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"允许应用停用状态栏或者增删系统图标。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"用作状态栏"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 0e65d66f7dd7..3b3018a89785 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以擷取在裝置指紋感應器上執行的手勢。"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕擷圖"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕截圖。"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"預覽,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改狀態列"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"成為狀態列"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index bd37579fb6f1..65967bd8ca83 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以擷取使用者對裝置的指紋感應器執行的手勢。"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕畫面"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕畫面。"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"預覽,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"停用或變更狀態列"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"以狀態列顯示"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index abc673bfb3b9..524ccb1c12ba 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -342,8 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Ingathatha ukuthinta okwenziwe kunzwa yezigxivizo zeminwe zedivayisi."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Thatha isithombe-skrini"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ingathatha isithombe-skrini sesiboniso"</string>
- <!-- no translation found for dream_preview_title (5570751491996100804) -->
- <skip />
+ <string name="dream_preview_title" msgid="5570751491996100804">"Hlola kuqala, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"khubaza noma guqula ibha yomumo"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ivumela uhlelo lokusebenza ukuthi yenze umudwa ochaza ngesimo ukuthi ungasebenzi noma ukufaka noma ukukhipha izithonjana zohlelo."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"yiba yibha yesimo"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index dafa0ad7989f..38913f5d2941 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -727,6 +727,9 @@
mode. -->
<integer name="config_unfoldTransitionHalfFoldedTimeout">1000</integer>
+ <!-- Timeout for receiving the keyguard drawn event from System UI. -->
+ <integer name="config_keyguardDrawnTimeout">1000</integer>
+
<!-- Indicates that the device supports having more than one internal display on at the same
time. Only applicable to devices with more than one internal display. If this option is
set to false, DisplayManager will make additional effort to ensure no more than 1 internal
@@ -6092,4 +6095,8 @@
<!-- Whether to show weather on the lock screen by default. -->
<bool name="config_lockscreenWeatherEnabledByDefault">false</bool>
+
+ <!-- Whether we should persist the brightness value in nits for the default display even if
+ the underlying display device changes. -->
+ <bool name="config_persistBrightnessNitsForDefaultDisplay">false</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 591ba5feeee9..a0d69e22e2c5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1987,6 +1987,7 @@
<java-symbol type="bool" name="config_allowTheaterModeWakeFromDock" />
<java-symbol type="bool" name="config_allowTheaterModeWakeFromWindowLayout" />
<java-symbol type="bool" name="config_keepDreamingWhenUndocking" />
+ <java-symbol type="integer" name="config_keyguardDrawnTimeout" />
<java-symbol type="bool" name="config_goToSleepOnButtonPressTheaterMode" />
<java-symbol type="bool" name="config_supportLongPressPowerWhenNonInteractive" />
<java-symbol type="bool" name="config_wimaxEnabled" />
@@ -2282,6 +2283,7 @@
<java-symbol type="bool" name="config_preventImeStartupUnlessTextEditor" />
<java-symbol type="array" name="config_nonPreemptibleInputMethods" />
<java-symbol type="bool" name="config_enhancedConfirmationModeEnabled" />
+ <java-symbol type="bool" name="config_persistBrightnessNitsForDefaultDisplay" />
<java-symbol type="layout" name="resolver_list" />
<java-symbol type="id" name="resolver_list" />
diff --git a/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java b/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
new file mode 100644
index 000000000000..9b9a84b79da3
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app.procstats;
+
+import static com.android.internal.app.procstats.ProcessStats.STATE_TOP;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import junit.framework.TestCase;
+
+import org.junit.Before;
+import org.mockito.Mock;
+
+import java.util.concurrent.TimeUnit;
+
+/** Provides test cases for ProcessStats. */
+public class ProcessStatsTest extends TestCase {
+
+ private static final String APP_1_PACKAGE_NAME = "com.android.testapp";
+ private static final int APP_1_UID = 5001;
+ private static final long APP_1_VERSION = 10;
+ private static final String APP_1_PROCESS_NAME = "com.android.testapp.p";
+ private static final String APP_1_SERVICE_NAME = "com.android.testapp.service";
+
+ private static final String APP_2_PACKAGE_NAME = "com.android.testapp2";
+ private static final int APP_2_UID = 5002;
+ private static final long APP_2_VERSION = 30;
+ private static final String APP_2_PROCESS_NAME = "com.android.testapp2.p";
+
+ private static final long NOW_MS = 123000;
+ private static final int DURATION_SECS = 6;
+
+ @Mock StatsEventOutput mStatsEventOutput;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ }
+
+ @SmallTest
+ public void testDumpProcessState() throws Exception {
+ ProcessStats processStats = new ProcessStats();
+ processStats.getProcessStateLocked(
+ APP_1_PACKAGE_NAME, APP_1_UID, APP_1_VERSION, APP_1_PROCESS_NAME);
+ processStats.getProcessStateLocked(
+ APP_2_PACKAGE_NAME, APP_2_UID, APP_2_VERSION, APP_2_PROCESS_NAME);
+ processStats.dumpProcessState(FrameworkStatsLog.PROCESS_STATE, mStatsEventOutput);
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_STATE),
+ eq(APP_1_UID),
+ eq(APP_1_PROCESS_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0));
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_STATE),
+ eq(APP_2_UID),
+ eq(APP_2_PROCESS_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0));
+ }
+
+ @SmallTest
+ public void testNonZeroProcessStateDuration() throws Exception {
+ ProcessStats processStats = new ProcessStats();
+ ProcessState processState =
+ processStats.getProcessStateLocked(
+ APP_1_PACKAGE_NAME, APP_1_UID, APP_1_VERSION, APP_1_PROCESS_NAME);
+ processState.setCombinedState(STATE_TOP, NOW_MS);
+ processState.commitStateTime(NOW_MS + TimeUnit.SECONDS.toMillis(DURATION_SECS));
+ processStats.dumpProcessState(FrameworkStatsLog.PROCESS_STATE, mStatsEventOutput);
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_STATE),
+ eq(APP_1_UID),
+ eq(APP_1_PROCESS_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(DURATION_SECS),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0));
+ }
+
+ @SmallTest
+ public void testDumpProcessAssociation() throws Exception {
+ ProcessStats processStats = new ProcessStats();
+ AssociationState associationState =
+ processStats.getAssociationStateLocked(
+ APP_1_PACKAGE_NAME,
+ APP_1_UID,
+ APP_1_VERSION,
+ APP_1_PROCESS_NAME,
+ APP_1_SERVICE_NAME);
+ AssociationState.SourceState sourceState =
+ associationState.startSource(APP_2_UID, APP_2_PROCESS_NAME, APP_2_PACKAGE_NAME);
+ sourceState.stop();
+ processStats.dumpProcessAssociation(
+ FrameworkStatsLog.PROCESS_ASSOCIATION, mStatsEventOutput);
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_ASSOCIATION),
+ eq(APP_2_UID),
+ eq(APP_2_PROCESS_NAME),
+ eq(APP_1_UID),
+ eq(APP_1_SERVICE_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(APP_1_PROCESS_NAME));
+ }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index caa118a409f5..e1c9b3c121f8 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -517,6 +517,12 @@ applications that come with the platform
<permission name="android.permission.BIND_WALLPAPER"/>
</privapp-permissions>
+ <privapp-permissions package="com.android.wallpaper">
+ <permission name="android.permission.SET_WALLPAPER_COMPONENT"/>
+ <permission name="android.permission.BIND_WALLPAPER"/>
+ <permission name="android.permission.CUSTOMIZE_SYSTEM_UI"/>
+ </privapp-permissions>
+
<privapp-permissions package="com.android.dynsystem">
<permission name="android.permission.REBOOT"/>
<permission name="android.permission.MANAGE_DYNAMIC_SYSTEM"/>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 1cf819af7a24..3d7fb16bb846 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1051,6 +1051,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/WindowContainer.java"
},
+ "-1104347731": {
+ "message": "Setting requested orientation %s for %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_ORIENTATION",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-1103716954": {
"message": "Not removing %s due to exit animation",
"level": "VERBOSE",
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 0f4521951e3d..c7c94246b96a 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -49,6 +49,7 @@ filegroup {
"src/com/android/wm/shell/animation/Interpolators.java",
"src/com/android/wm/shell/pip/PipContentOverlay.java",
"src/com/android/wm/shell/startingsurface/SplashScreenExitAnimationUtils.java",
+ "src/com/android/wm/shell/draganddrop/DragAndDropConstants.java",
],
path: "src",
}
diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS
index 4b125904004a..852edef544b8 100644
--- a/libs/WindowManager/Shell/OWNERS
+++ b/libs/WindowManager/Shell/OWNERS
@@ -1,4 +1,4 @@
xutan@google.com
# Give submodule owners in shell resource approval
-per-file res*/*/*.xml = hwwang@google.com, lbill@google.com, madym@google.com
+per-file res*/*/*.xml = hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com
diff --git a/libs/WindowManager/Shell/res/color/split_divider_background.xml b/libs/WindowManager/Shell/res/color-night/taskbar_background.xml
index 049980803ee3..9473cdd607d6 100644
--- a/libs/WindowManager/Shell/res/color/split_divider_background.xml
+++ b/libs/WindowManager/Shell/res/color-night/taskbar_background.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2021 The Android Open Source Project
+ ~ Copyright (C) 2023 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
+<!-- Should be the same as in packages/apps/Launcher3/res/color-night-v31/taskbar_background.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/system_neutral1_500" android:lStar="15" />
</selector> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/color/taskbar_background.xml b/libs/WindowManager/Shell/res/color/taskbar_background.xml
index b3d260299106..0e165fca4fd3 100644
--- a/libs/WindowManager/Shell/res/color/taskbar_background.xml
+++ b/libs/WindowManager/Shell/res/color/taskbar_background.xml
@@ -16,5 +16,5 @@
-->
<!-- Should be the same as in packages/apps/Launcher3/res/color-v31/taskbar_background.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="15" />
+ <item android:color="@android:color/system_neutral1_500" android:lStar="95" />
</selector> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml b/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
index 9167382d0898..c6e634c6622c 100644
--- a/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
+++ b/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
@@ -17,6 +17,6 @@
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white" />
- <corners android:radius="20dp" />
+ <corners android:radius="@dimen/caption_menu_corner_radius" />
<stroke android:width="1dp" android:color="#b3b3b3"/>
</shape>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml
deleted file mode 100644
index 0d8811357c05..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@color/letterbox_education_accent_primary"/>
- <corners android:radius="12dp"/>
-</shape> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
index 42572d64b96f..a2699681e656 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
@@ -14,7 +14,30 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_education_dismiss_button_background_ripple">
- <item android:drawable="@drawable/letterbox_education_dismiss_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetTop="@dimen/letterbox_education_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_education_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_education_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_education_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@color/letterbox_education_accent_primary"/>
+ <corners android:radius="@dimen/letterbox_education_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_education_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_education_dialog_vertical_padding"
+ android:right="@dimen/letterbox_education_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_education_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
index ef97ea19e993..1f125148775d 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
@@ -14,7 +14,31 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_restart_button_background_ripple">
- <item android:drawable="@drawable/letterbox_restart_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:insetTop="@dimen/letterbox_restart_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_restart_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_restart_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_restart_dialog_vertical_padding"
+ android:right="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_restart_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml
deleted file mode 100644
index af89d41ee6b5..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="rectangle">
- <stroke android:color="?androidprv:attr/colorAccentPrimaryVariant" android:width="1dp"/>
- <solid android:color="?androidprv:attr/colorSurface" />
- <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
-</shape> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
index e32aefca78ac..3aa0981e45aa 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
@@ -14,7 +14,33 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_restart_dismiss_button_background_ripple">
- <item android:drawable="@drawable/letterbox_restart_dismiss_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:insetTop="@dimen/letterbox_restart_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_restart_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_restart_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <stroke android:color="?androidprv:attr/colorAccentPrimaryVariant"
+ android:width="1dp"/>
+ <solid android:color="?androidprv:attr/colorSurface"/>
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_restart_dialog_vertical_padding"
+ android:right="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_restart_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml b/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
index 44b2f45052ba..3d3c00381164 100644
--- a/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
+++ b/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
@@ -29,11 +29,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="4sp"
+ android:letterSpacing="0.02"
android:background="@drawable/compat_hint_bubble"
android:padding="16dp"
android:textAlignment="viewStart"
android:textColor="@color/compat_controls_text"
- android:textSize="14sp"/>
+ android:textSize="14sp"
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
+ />
<ImageView
android:layout_width="wrap_content"
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
index f6e3f2edfa14..f9aeb6a8448a 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
@@ -21,7 +21,6 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/desktop_mode_decor_menu_background"
- android:elevation="@dimen/caption_menu_elevation"
android:divider="?android:attr/dividerHorizontal"
android:showDividers="middle"
android:dividerPadding="18dip">
@@ -63,38 +62,46 @@
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="0.5" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/fullscreen_button"
android:contentDescription="@string/fullscreen_text"
- android:background="@drawable/caption_fullscreen_button"/>
+ android:src="@drawable/caption_fullscreen_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/split_screen_button"
android:contentDescription="@string/split_screen_text"
- android:background="@drawable/caption_split_screen_button"/>
+ android:src="@drawable/caption_split_screen_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/floating_button"
android:contentDescription="@string/float_button_text"
- android:background="@drawable/caption_floating_button"/>
+ android:src="@drawable/caption_floating_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/desktop_button"
android:contentDescription="@string/desktop_text"
- android:background="@drawable/caption_desktop_button"/>
+ android:src="@drawable/caption_desktop_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
index c65f24d84e37..095576b581df 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
@@ -29,6 +29,8 @@
android:layout_marginBottom="20dp"/>
<TextView
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"
android:id="@+id/letterbox_education_dialog_action_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
index 3a44eb9089dd..413cfd78fd91 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
@@ -16,9 +16,7 @@
<com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@android:color/system_neutral1_900">
+ style="@style/LetterboxDialog">
<!-- The background of the top-level layout acts as the background dim. -->
@@ -69,6 +67,8 @@
android:text="@string/letterbox_education_dialog_title"
android:textAlignment="center"
android:textColor="@color/compat_controls_text"
+ android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Headline"
android:textSize="24sp"/>
<LinearLayout
@@ -95,10 +95,16 @@
</LinearLayout>
<Button
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:fontWeight="500"
+ android:lineHeight="20dp"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Small"
android:id="@+id/letterbox_education_dialog_dismiss_button"
+ android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="40dp"
+ android:textSize="14sp"
android:background=
"@drawable/letterbox_education_dismiss_button_background_ripple"
android:text="@string/letterbox_education_got_it"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
index ba9852c4dd6b..5aff4159e135 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
@@ -16,14 +16,10 @@
<com.android.wm.shell.compatui.RestartDialogLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@android:color/system_neutral1_900">
+ style="@style/LetterboxDialog">
<!-- The background of the top-level layout acts as the background dim. -->
- <!--TODO (b/266288912): Resolve overdraw warning -->
-
<!-- Vertical margin will be set dynamically since it depends on task bounds.
Setting the alpha of the dialog container to 0, since it shouldn't be visible until the
enter animation starts. -->
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index 22d921960174..0a5134ed2e59 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Maak toe"</string>
<string name="back_button_text" msgid="1469718707134137085">"Terug"</string>
<string name="handle_text" msgid="1766582106752184456">"Handvatsel"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Appikoon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Volskerm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Rekenaarmodus"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Verdeelde skerm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Meer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Sweef"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Kies"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skermskoot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Maak toe"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Maak kieslys toe"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index 17ea0530de52..6734195b74fe 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ዝጋ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ተመለስ"</string>
<string name="handle_text" msgid="1766582106752184456">"መያዣ"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"የመተግበሪያ አዶ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ሙሉ ማያ"</string>
<string name="desktop_text" msgid="1077633567027630454">"የዴስክቶፕ ሁነታ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"የተከፈለ ማያ ገጽ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ተጨማሪ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ተንሳፋፊ"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"ምረጥ"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ቅጽበታዊ ገጽ እይታ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ዝጋ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ምናሌ ዝጋ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 2e4c8ef29862..6bef71a11ad9 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -47,14 +47,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ضبط حجم النافذة العلوية ليكون ٥٠%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ضبط حجم النافذة العلوية ليكون ٣٠%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"عرض النافذة السفلية بملء الشاشة"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"تقسيم لليسار"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"تقسيم لليمين"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"تقسيم للأعلى"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"تقسيم للأسفل"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"استخدام وضع \"التصفح بيد واحدة\""</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"للخروج، مرِّر سريعًا من أسفل الشاشة إلى أعلاها أو انقر في أي مكان فوق التطبيق."</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"بدء وضع \"التصفح بيد واحدة\""</string>
@@ -100,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"إغلاق"</string>
<string name="back_button_text" msgid="1469718707134137085">"رجوع"</string>
<string name="handle_text" msgid="1766582106752184456">"مقبض"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"رمز التطبيق"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ملء الشاشة"</string>
<string name="desktop_text" msgid="1077633567027630454">"وضع سطح المكتب"</string>
<string name="split_screen_text" msgid="1396336058129570886">"تقسيم الشاشة"</string>
<string name="more_button_text" msgid="3655388105592893530">"المزيد"</string>
<string name="float_button_text" msgid="9221657008391364581">"نافذة عائمة"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"اختيار"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"لقطة شاشة"</string>
+ <string name="close_text" msgid="4986518933445178928">"إغلاق"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"إغلاق القائمة"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index c88519736ad6..48b93ceac087 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"বন্ধ কৰক"</string>
<string name="back_button_text" msgid="1469718707134137085">"উভতি যাওক"</string>
<string name="handle_text" msgid="1766582106752184456">"হেণ্ডেল"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"এপৰ চিহ্ন"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"সম্পূৰ্ণ স্ক্ৰীন"</string>
<string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ ম’ড"</string>
<string name="split_screen_text" msgid="1396336058129570886">"বিভাজিত স্ক্ৰীন"</string>
<string name="more_button_text" msgid="3655388105592893530">"অধিক"</string>
<string name="float_button_text" msgid="9221657008391364581">"ওপঙা"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"বাছনি কৰক"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"স্ক্ৰীনশ্বট"</string>
+ <string name="close_text" msgid="4986518933445178928">"বন্ধ কৰক"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"মেনু বন্ধ কৰক"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index 4427fa94c8fc..8233dd3a1605 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Bağlayın"</string>
<string name="back_button_text" msgid="1469718707134137085">"Geriyə"</string>
<string name="handle_text" msgid="1766582106752184456">"Hər kəsə açıq istifadəçi adı"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Tətbiq ikonası"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Masaüstü Rejimi"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Bölünmüş Ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Ardı"</string>
<string name="float_button_text" msgid="9221657008391364581">"Üzən pəncərə"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Seçin"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skrinşot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Bağlayın"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menyunu bağlayın"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index a67ba393180e..34c42a98564f 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zatvorite"</string>
<string name="back_button_text" msgid="1469718707134137085">"Nazad"</string>
<string name="handle_text" msgid="1766582106752184456">"Identifikator"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Preko celog ekrana"</string>
<string name="desktop_text" msgid="1077633567027630454">"Režim za računare"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Podeljeni ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Još"</string>
<string name="float_button_text" msgid="9221657008391364581">"Plutajuće"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Izaberite"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Snimak ekrana"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zatvorite"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite meni"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index 5adb2ecec112..4f21e7319f48 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Закрыць"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Значок праграмы"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"На ўвесь экран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Рэжым працоўнага стала"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Падзяліць экран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Яшчэ"</string>
<string name="float_button_text" msgid="9221657008391364581">"Зрабіць рухомым акном"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Выбраць"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Здымак экрана"</string>
+ <string name="close_text" msgid="4986518933445178928">"Закрыць"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Закрыць меню"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index 8c82d1a7c94f..94146494ba0b 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Затваряне"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Манипулатор"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Икона на приложението"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Цял екран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим за настолни компютри"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Разделяне на екрана"</string>
<string name="more_button_text" msgid="3655388105592893530">"Още"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плаващо"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Избиране"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Екранна снимка"</string>
+ <string name="close_text" msgid="4986518933445178928">"Затваряне"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Затваряне на менюто"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index 11a4175c0bb0..1718b51bb058 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -47,14 +47,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"শীর্ষ ৫০%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"শীর্ষ ৩০%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"নীচের অংশ নিয়ে পূর্ণ স্ক্রিন"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"স্ক্রিনের বাঁদিকে স্প্লিট করুন"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"স্ক্রিনের ডানদিকে স্প্লিট করুন"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"স্ক্রিনের উপরের দিকে স্প্লিট করুন"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"স্প্লিট করার বোতাম"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"\'এক হাতে ব্যবহার করার মোড\'-এর ব্যবহার"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"বেরিয়ে আসার জন্য, স্ক্রিনের নিচ থেকে উপরের দিকে সোয়াইপ করুন অথবা অ্যাপ আইকনের উপরে যেকোনও জায়গায় ট্যাপ করুন"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"\'এক হাতে ব্যবহার করার মোড\' শুরু করুন"</string>
@@ -100,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"বন্ধ করুন"</string>
<string name="back_button_text" msgid="1469718707134137085">"ফিরে যান"</string>
<string name="handle_text" msgid="1766582106752184456">"হাতল"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"অ্যাপ আইকন"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ফুলস্ক্রিন"</string>
<string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ মোড"</string>
<string name="split_screen_text" msgid="1396336058129570886">"স্প্লিট স্ক্রিন"</string>
<string name="more_button_text" msgid="3655388105592893530">"আরও"</string>
<string name="float_button_text" msgid="9221657008391364581">"ফ্লোট"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"বেছে নিন"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"স্ক্রিনশট"</string>
+ <string name="close_text" msgid="4986518933445178928">"বন্ধ করুন"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"\'মেনু\' বন্ধ করুন"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index c65ce0842db7..440cfad9f988 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -102,8 +102,8 @@
<string name="split_screen_text" msgid="1396336058129570886">"Podijeljeni ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Više"</string>
<string name="float_button_text" msgid="9221657008391364581">"Lebdeći"</string>
- <string name="select_text" msgid="5139083974039906583">"Odaberite"</string>
- <string name="screenshot_text" msgid="1477704010087786671">"Snimka zaslona"</string>
- <string name="close_text" msgid="4986518933445178928">"Zatvorite"</string>
- <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite izbornik"</string>
+ <string name="select_text" msgid="5139083974039906583">"Odabir"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Snimak ekrana"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zatvaranje"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvaranje menija"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index f50b8f295a32..a19706a61108 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Tanca"</string>
<string name="back_button_text" msgid="1469718707134137085">"Enrere"</string>
<string name="handle_text" msgid="1766582106752184456">"Ansa"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Icona de l\'aplicació"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode d\'escriptori"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Més"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotant"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Selecciona"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de pantalla"</string>
+ <string name="close_text" msgid="4986518933445178928">"Tanca"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Tanca el menú"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index ac36edbb2f6e..684a6ff2b078 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zavřít"</string>
<string name="back_button_text" msgid="1469718707134137085">"Zpět"</string>
<string name="handle_text" msgid="1766582106752184456">"Úchyt"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikace"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Celá obrazovka"</string>
<string name="desktop_text" msgid="1077633567027630454">"Režim počítače"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Rozdělená obrazovka"</string>
<string name="more_button_text" msgid="3655388105592893530">"Více"</string>
<string name="float_button_text" msgid="9221657008391364581">"Plovoucí"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Vybrat"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Snímek obrazovky"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zavřít"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zavřít nabídku"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index 8635cc5d4632..140610db8c2f 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Luk"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tilbage"</string>
<string name="handle_text" msgid="1766582106752184456">"Håndtag"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fuld skærm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Computertilstand"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Opdelt skærm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mere"</string>
<string name="float_button_text" msgid="9221657008391364581">"Svævende"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Vælg"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Luk"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Luk menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index 059a4da313fe..cd1213d25e4e 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Schließen"</string>
<string name="back_button_text" msgid="1469718707134137085">"Zurück"</string>
<string name="handle_text" msgid="1766582106752184456">"Ziehpunkt"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"App-Symbol"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Vollbild"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Geteilter Bildschirm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mehr"</string>
<string name="float_button_text" msgid="9221657008391364581">"Frei schwebend"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Auswählen"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Schließen"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menü schließen"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index 5800cc826ef2..2e6b912e1ab1 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Κλείσιμο"</string>
<string name="back_button_text" msgid="1469718707134137085">"Πίσω"</string>
<string name="handle_text" msgid="1766582106752184456">"Λαβή"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Εικονίδιο εφαρμογής"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Πλήρης οθόνη"</string>
<string name="desktop_text" msgid="1077633567027630454">"Λειτουργία επιφάνειας εργασίας"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Διαχωρισμός οθόνης"</string>
<string name="more_button_text" msgid="3655388105592893530">"Περισσότερα"</string>
<string name="float_button_text" msgid="9221657008391364581">"Κινούμενο"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Επιλογή"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Στιγμιότυπο οθόνης"</string>
+ <string name="close_text" msgid="4986518933445178928">"Κλείσιμο"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Κλείσιμο μενού"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index d30653759f2f..f1357d8c066d 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atrás"</string>
<string name="handle_text" msgid="1766582106752184456">"Controlador"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ícono de la app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo de escritorio"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Más"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotante"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Seleccionar"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de pantalla"</string>
+ <string name="close_text" msgid="4986518933445178928">"Cerrar"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Cerrar menú"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index ab1ced4f6d1e..9aa3d60db440 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atrás"</string>
<string name="handle_text" msgid="1766582106752184456">"Controlador"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Icono de la aplicación"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo Escritorio"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Más"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotante"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Seleccionar"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de pantalla"</string>
+ <string name="close_text" msgid="4986518933445178928">"Cerrar"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Cerrar menú"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index 4c4d87ebf574..1e13283132d3 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Sule"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tagasi"</string>
<string name="handle_text" msgid="1766582106752184456">"Käepide"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Rakenduse ikoon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Täisekraan"</string>
<string name="desktop_text" msgid="1077633567027630454">"Lauaarvuti režiim"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Jagatud ekraanikuva"</string>
<string name="more_button_text" msgid="3655388105592893530">"Rohkem"</string>
<string name="float_button_text" msgid="9221657008391364581">"Hõljuv"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Vali"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Ekraanipilt"</string>
+ <string name="close_text" msgid="4986518933445178928">"Sule"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Sule menüü"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index 5642a5f33115..72e94dc2dc6e 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Itxi"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atzera"</string>
<string name="handle_text" msgid="1766582106752184456">"Kontu-izena"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Aplikazioaren ikonoa"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantaila osoa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Ordenagailuetarako modua"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Pantaila zatitua"</string>
<string name="more_button_text" msgid="3655388105592893530">"Gehiago"</string>
<string name="float_button_text" msgid="9221657008391364581">"Leiho gainerakorra"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Hautatu"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Pantaila-argazkia"</string>
+ <string name="close_text" msgid="4986518933445178928">"Itxi"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Itxi menua"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index a15d7a4e1c1f..1cc5faaedb0e 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"بستن"</string>
<string name="back_button_text" msgid="1469718707134137085">"برگشتن"</string>
<string name="handle_text" msgid="1766582106752184456">"دستگیره"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"نماد برنامه"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"تمام‌صفحه"</string>
<string name="desktop_text" msgid="1077633567027630454">"حالت رایانه"</string>
<string name="split_screen_text" msgid="1396336058129570886">"صفحهٔ دونیمه"</string>
<string name="more_button_text" msgid="3655388105592893530">"بیشتر"</string>
<string name="float_button_text" msgid="9221657008391364581">"شناور"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"انتخاب"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"نماگرفت"</string>
+ <string name="close_text" msgid="4986518933445178928">"بستن"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"بستن منو"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index 8c679b6b6ff7..ee6f995dd19a 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Sulje"</string>
<string name="back_button_text" msgid="1469718707134137085">"Takaisin"</string>
<string name="handle_text" msgid="1766582106752184456">"Kahva"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Sovelluskuvake"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Koko näyttö"</string>
<string name="desktop_text" msgid="1077633567027630454">"Työpöytätila"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Jaettu näyttö"</string>
<string name="more_button_text" msgid="3655388105592893530">"Lisää"</string>
<string name="float_button_text" msgid="9221657008391364581">"Kelluva ikkuna"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Valitse"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Kuvakaappaus"</string>
+ <string name="close_text" msgid="4986518933445178928">"Sulje"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Sulje valikko"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index d43aea5849d1..283876c0e55b 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
<string name="back_button_text" msgid="1469718707134137085">"Retour"</string>
<string name="handle_text" msgid="1766582106752184456">"Identifiant"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Icône de l\'application"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode Bureau"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Écran partagé"</string>
<string name="more_button_text" msgid="3655388105592893530">"Plus"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flottant"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Sélectionner"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Capture d\'écran"</string>
+ <string name="close_text" msgid="4986518933445178928">"Fermer"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Fermer le menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index 15e89f81682e..4e80360a1e34 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
<string name="back_button_text" msgid="1469718707134137085">"Retour"</string>
<string name="handle_text" msgid="1766582106752184456">"Poignée"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Icône d\'application"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode ordinateur"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Écran partagé"</string>
<string name="more_button_text" msgid="3655388105592893530">"Plus"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flottante"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Sélectionner"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Capture d\'écran"</string>
+ <string name="close_text" msgid="4986518933445178928">"Fermer"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Fermer le menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index f83564d05f44..974a687717d7 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Pechar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atrás"</string>
<string name="handle_text" msgid="1766582106752184456">"Controlador"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Icona de aplicación"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo de escritorio"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Máis"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotante"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Seleccionar"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de pantalla"</string>
+ <string name="close_text" msgid="4986518933445178928">"Pechar"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Pechar o menú"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index bd3620591cf7..be8a9ff9b4ec 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"બંધ કરો"</string>
<string name="back_button_text" msgid="1469718707134137085">"પાછળ"</string>
<string name="handle_text" msgid="1766582106752184456">"હૅન્ડલ"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"ઍપનું આઇકન"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"પૂર્ણસ્ક્રીન"</string>
<string name="desktop_text" msgid="1077633567027630454">"ડેસ્કટૉપ મોડ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"સ્ક્રીનને વિભાજિત કરો"</string>
<string name="more_button_text" msgid="3655388105592893530">"વધુ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ફ્લોટિંગ વિન્ડો"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"પસંદ કરો"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"સ્ક્રીનશૉટ"</string>
+ <string name="close_text" msgid="4986518933445178928">"બંધ કરો"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"મેનૂ બંધ કરો"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index e56ad17d2680..120ecc92e777 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"बंद करें"</string>
<string name="back_button_text" msgid="1469718707134137085">"वापस जाएं"</string>
<string name="handle_text" msgid="1766582106752184456">"हैंडल"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"ऐप्लिकेशन आइकॉन"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"फ़ुलस्क्रीन"</string>
<string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string>
<string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रीन मोड"</string>
<string name="more_button_text" msgid="3655388105592893530">"ज़्यादा देखें"</string>
<string name="float_button_text" msgid="9221657008391364581">"फ़्लोट"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"चुनें"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"स्क्रीनशॉट"</string>
+ <string name="close_text" msgid="4986518933445178928">"बंद करें"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"मेन्यू बंद करें"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index 28536e67952f..7edd9151f660 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Bezárás"</string>
<string name="back_button_text" msgid="1469718707134137085">"Vissza"</string>
<string name="handle_text" msgid="1766582106752184456">"Fogópont"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Alkalmazásikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Teljes képernyő"</string>
<string name="desktop_text" msgid="1077633567027630454">"Asztali üzemmód"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Osztott képernyő"</string>
<string name="more_button_text" msgid="3655388105592893530">"Továbbiak"</string>
<string name="float_button_text" msgid="9221657008391364581">"Lebegő"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Kiválasztás"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Képernyőkép"</string>
+ <string name="close_text" msgid="4986518933445178928">"Bezárás"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menü bezárása"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index bd3508482f7c..94950a0d3e74 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Փակել"</string>
<string name="back_button_text" msgid="1469718707134137085">"Հետ"</string>
<string name="handle_text" msgid="1766582106752184456">"Նշիչ"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Հավելվածի պատկերակ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Լիաէկրան"</string>
<string name="desktop_text" msgid="1077633567027630454">"Համակարգչի ռեժիմ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Տրոհված էկրան"</string>
<string name="more_button_text" msgid="3655388105592893530">"Ավելին"</string>
<string name="float_button_text" msgid="9221657008391364581">"Լողացող պատուհան"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Ընտրել"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Սքրինշոթ"</string>
+ <string name="close_text" msgid="4986518933445178928">"Փակել"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Փակել ընտրացանկը"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index 6f859ed8ef29..890b86ac71e1 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Tutup"</string>
<string name="back_button_text" msgid="1469718707134137085">"Kembali"</string>
<string name="handle_text" msgid="1766582106752184456">"Tuas"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikon Aplikasi"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Layar Penuh"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode Desktop"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Layar Terpisah"</string>
<string name="more_button_text" msgid="3655388105592893530">"Lainnya"</string>
<string name="float_button_text" msgid="9221657008391364581">"Mengambang"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Pilih"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Tutup"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Tutup Menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index b17abf593cd7..f4a9a57b293e 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Loka"</string>
<string name="back_button_text" msgid="1469718707134137085">"Til baka"</string>
<string name="handle_text" msgid="1766582106752184456">"Handfang"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Tákn forrits"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Allur skjárinn"</string>
<string name="desktop_text" msgid="1077633567027630454">"Skjáborðsstilling"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Skjáskipting"</string>
<string name="more_button_text" msgid="3655388105592893530">"Meira"</string>
<string name="float_button_text" msgid="9221657008391364581">"Reikult"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Velja"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skjámynd"</string>
+ <string name="close_text" msgid="4986518933445178928">"Loka"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Loka valmynd"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index 28e274bce7d6..4647e9a48630 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Chiudi"</string>
<string name="back_button_text" msgid="1469718707134137085">"Indietro"</string>
<string name="handle_text" msgid="1766582106752184456">"Handle"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Icona dell\'app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Schermo intero"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modalità desktop"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Schermo diviso"</string>
<string name="more_button_text" msgid="3655388105592893530">"Altro"</string>
<string name="float_button_text" msgid="9221657008391364581">"Mobile"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Seleziona"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Chiudi"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Chiudi il menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index 497e0b0c7884..5dd99d087551 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"סגירה"</string>
<string name="back_button_text" msgid="1469718707134137085">"חזרה"</string>
<string name="handle_text" msgid="1766582106752184456">"נקודת אחיזה"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"סמל האפליקציה"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"מסך מלא"</string>
<string name="desktop_text" msgid="1077633567027630454">"ממשק המחשב"</string>
<string name="split_screen_text" msgid="1396336058129570886">"מסך מפוצל"</string>
<string name="more_button_text" msgid="3655388105592893530">"עוד"</string>
<string name="float_button_text" msgid="9221657008391364581">"בלונים"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"בחירה"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"צילום מסך"</string>
+ <string name="close_text" msgid="4986518933445178928">"סגירה"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"סגירת התפריט"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 7f7cd940619d..bde3eb1c8d44 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"閉じる"</string>
<string name="back_button_text" msgid="1469718707134137085">"戻る"</string>
<string name="handle_text" msgid="1766582106752184456">"ハンドル"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"アプリのアイコン"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全画面表示"</string>
<string name="desktop_text" msgid="1077633567027630454">"デスクトップ モード"</string>
<string name="split_screen_text" msgid="1396336058129570886">"分割画面"</string>
<string name="more_button_text" msgid="3655388105592893530">"その他"</string>
<string name="float_button_text" msgid="9221657008391364581">"フローティング"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"選択"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"スクリーンショット"</string>
+ <string name="close_text" msgid="4986518933445178928">"閉じる"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"メニューを閉じる"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index deec26db2a8d..a455c74cbae0 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"დახურვა"</string>
<string name="back_button_text" msgid="1469718707134137085">"უკან"</string>
<string name="handle_text" msgid="1766582106752184456">"იდენტიფიკატორი"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"აპის ხატულა"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"სრულ ეკრანზე"</string>
<string name="desktop_text" msgid="1077633567027630454">"დესკტოპის რეჟიმი"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ეკრანის გაყოფა"</string>
<string name="more_button_text" msgid="3655388105592893530">"სხვა"</string>
<string name="float_button_text" msgid="9221657008391364581">"ფარფატი"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"არჩევა"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ეკრანის ანაბეჭდი"</string>
+ <string name="close_text" msgid="4986518933445178928">"დახურვა"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"მენიუს დახურვა"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index d429ba95df18..16189e0a76f9 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Жабу"</string>
<string name="back_button_text" msgid="1469718707134137085">"Артқа"</string>
<string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Қолданба белгішесі"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Толық экран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Компьютер режимі"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Экранды бөлу"</string>
<string name="more_button_text" msgid="3655388105592893530">"Қосымша"</string>
<string name="float_button_text" msgid="9221657008391364581">"Қалқыма"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Таңдау"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Скриншот"</string>
+ <string name="close_text" msgid="4986518933445178928">"Жабу"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Мәзірді жабу"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index bfcf40bad5ef..70bcdbf07533 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"បិទ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ថយក្រោយ"</string>
<string name="handle_text" msgid="1766582106752184456">"ឈ្មោះអ្នកប្រើប្រាស់"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"រូប​កម្មវិធី"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"អេក្រង់​ពេញ"</string>
<string name="desktop_text" msgid="1077633567027630454">"មុខងារកុំព្យូទ័រ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"មុខងារ​បំបែក​អេក្រង់"</string>
<string name="more_button_text" msgid="3655388105592893530">"ច្រើនទៀត"</string>
<string name="float_button_text" msgid="9221657008391364581">"អណ្ដែត"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"ជ្រើសរើស"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"រូបថតអេក្រង់"</string>
+ <string name="close_text" msgid="4986518933445178928">"បិទ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"បិទ​ម៉ឺនុយ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 9d2515c396eb..86cc71c1b41e 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ಮುಚ್ಚಿರಿ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ಹಿಂದಕ್ಕೆ"</string>
<string name="handle_text" msgid="1766582106752184456">"ಹ್ಯಾಂಡಲ್"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"ಆ್ಯಪ್ ಐಕಾನ್"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ಫುಲ್‌ಸ್ಕ್ರೀನ್"</string>
<string name="desktop_text" msgid="1077633567027630454">"ಡೆಸ್ಕ್‌ಟಾಪ್ ಮೋಡ್"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್"</string>
<string name="more_button_text" msgid="3655388105592893530">"ಇನ್ನಷ್ಟು"</string>
<string name="float_button_text" msgid="9221657008391364581">"ಫ್ಲೋಟ್"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"ಆಯ್ಕೆಮಾಡಿ"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
+ <string name="close_text" msgid="4986518933445178928">"ಮುಚ್ಚಿ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ಮೆನು ಮುಚ್ಚಿ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index 55007fc3de0a..d9711e512774 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"닫기"</string>
<string name="back_button_text" msgid="1469718707134137085">"뒤로"</string>
<string name="handle_text" msgid="1766582106752184456">"핸들"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"앱 아이콘"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"전체 화면"</string>
<string name="desktop_text" msgid="1077633567027630454">"데스크톱 모드"</string>
<string name="split_screen_text" msgid="1396336058129570886">"화면 분할"</string>
<string name="more_button_text" msgid="3655388105592893530">"더보기"</string>
<string name="float_button_text" msgid="9221657008391364581">"플로팅"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"선택"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"스크린샷"</string>
+ <string name="close_text" msgid="4986518933445178928">"닫기"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"메뉴 닫기"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index 9691dbae4bbc..391c3afe57e4 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Жабуу"</string>
<string name="back_button_text" msgid="1469718707134137085">"Артка"</string>
<string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Колдонмонун сүрөтчөсү"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Толук экран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Компьютер режими"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Экранды бөлүү"</string>
<string name="more_button_text" msgid="3655388105592893530">"Дагы"</string>
<string name="float_button_text" msgid="9221657008391364581">"Калкыма"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Тандоо"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Скриншот"</string>
+ <string name="close_text" msgid="4986518933445178928">"Жабуу"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Менюну жабуу"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index 678e0859272a..bc1ac739c99a 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ປິດ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ກັບຄືນ"</string>
<string name="handle_text" msgid="1766582106752184456">"ມືບັງຄັບ"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"ໄອຄອນແອັບ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ເຕັມຈໍ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ໂໝດເດັສທັອບ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ແບ່ງໜ້າຈໍ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ເພີ່ມເຕີມ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ລອຍ"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"ເລືອກ"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ຮູບໜ້າຈໍ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ປິດ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ປິດເມນູ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index f8a2a0fc0671..6dc5b444437a 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Uždaryti"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atgal"</string>
<string name="handle_text" msgid="1766582106752184456">"Rankenėlė"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Programos piktograma"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Visas ekranas"</string>
<string name="desktop_text" msgid="1077633567027630454">"Stalinio kompiuterio režimas"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Išskaidyto ekrano režimas"</string>
<string name="more_button_text" msgid="3655388105592893530">"Daugiau"</string>
<string name="float_button_text" msgid="9221657008391364581">"Slankusis langas"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Pasirinkti"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Ekrano kopija"</string>
+ <string name="close_text" msgid="4986518933445178928">"Uždaryti"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Uždaryti meniu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index d14bb67936d3..76d8db39947d 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Aizvērt"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atpakaļ"</string>
<string name="handle_text" msgid="1766582106752184456">"Turis"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Lietotnes ikona"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pilnekrāna režīms"</string>
<string name="desktop_text" msgid="1077633567027630454">"Darbvirsmas režīms"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Sadalīt ekrānu"</string>
<string name="more_button_text" msgid="3655388105592893530">"Vairāk"</string>
<string name="float_button_text" msgid="9221657008391364581">"Peldošs"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Atlasīt"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Ekrānuzņēmums"</string>
+ <string name="close_text" msgid="4986518933445178928">"Aizvērt"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Aizvērt izvēlni"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index 45aeb7f332b0..190f7293228c 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -47,14 +47,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Горниот 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Горниот 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Долниот на цел екран"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Подели налево"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Подели надесно"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Подели нагоре"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Подели долу"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Користење на режимот со една рака"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"За да излезете, повлечете нагоре од дното на екранот или допрете каде било над апликацијата"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Започни го режимот со една рака"</string>
@@ -100,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Затвори"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Прекар"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Икона на апликацијата"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Цел екран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим за компјутер"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Поделен екран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Повеќе"</string>
<string name="float_button_text" msgid="9221657008391364581">"Лебдечко"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Изберете"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Слика од екранот"</string>
+ <string name="close_text" msgid="4986518933445178928">"Затворете"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Затворете го менито"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index ca5f0f7c4941..7307f20f8dc3 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"അടയ്ക്കുക"</string>
<string name="back_button_text" msgid="1469718707134137085">"മടങ്ങുക"</string>
<string name="handle_text" msgid="1766582106752184456">"ഹാൻഡിൽ"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"ആപ്പ് ഐക്കൺ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"പൂർണ്ണസ്ക്രീൻ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ഡെസ്‌ക്ടോപ്പ് മോഡ്"</string>
<string name="split_screen_text" msgid="1396336058129570886">"സ്‌ക്രീൻ വിഭജനം"</string>
<string name="more_button_text" msgid="3655388105592893530">"കൂടുതൽ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ഫ്ലോട്ട്"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"തിരഞ്ഞെടുക്കുക"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"സ്ക്രീൻഷോട്ട്"</string>
+ <string name="close_text" msgid="4986518933445178928">"അടയ്ക്കുക"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"മെനു അടയ്ക്കുക"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index 9678c5c7190e..bc43b7037b91 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Хаах"</string>
<string name="back_button_text" msgid="1469718707134137085">"Буцах"</string>
<string name="handle_text" msgid="1766582106752184456">"Бариул"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Aппын дүрс тэмдэг"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Бүтэн дэлгэц"</string>
<string name="desktop_text" msgid="1077633567027630454">"Дэлгэцийн горим"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Дэлгэцийг хуваах"</string>
<string name="more_button_text" msgid="3655388105592893530">"Бусад"</string>
<string name="float_button_text" msgid="9221657008391364581">"Хөвөгч"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Сонгох"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Дэлгэцийн агшин"</string>
+ <string name="close_text" msgid="4986518933445178928">"Хаах"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Цэсийг хаах"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index ea728e844cb7..a31056dec589 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"बंद करा"</string>
<string name="back_button_text" msgid="1469718707134137085">"मागे जा"</string>
<string name="handle_text" msgid="1766582106752184456">"हँडल"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"अ‍ॅप आयकन"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"फुलस्‍क्रीन"</string>
<string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string>
<string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रीन"</string>
<string name="more_button_text" msgid="3655388105592893530">"आणखी"</string>
<string name="float_button_text" msgid="9221657008391364581">"फ्लोट"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"निवडा"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"स्क्रीनशॉट"</string>
+ <string name="close_text" msgid="4986518933445178928">"बंद करा"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"मेनू बंद करा"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index 8a9b81c9e333..8435ccf10a95 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Tutup"</string>
<string name="back_button_text" msgid="1469718707134137085">"Kembali"</string>
<string name="handle_text" msgid="1766582106752184456">"Pemegang"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikon Apl"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Skrin penuh"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mod Desktop"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Skrin Pisah"</string>
<string name="more_button_text" msgid="3655388105592893530">"Lagi"</string>
<string name="float_button_text" msgid="9221657008391364581">"Terapung"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Pilih"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Tangkapan skrin"</string>
+ <string name="close_text" msgid="4986518933445178928">"Tutup"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Tutup Menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index b37bfa7fcaf6..acc9130a5091 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ပိတ်ရန်"</string>
<string name="back_button_text" msgid="1469718707134137085">"နောက်သို့"</string>
<string name="handle_text" msgid="1766582106752184456">"သုံးသူအမည်"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"အက်ပ်သင်္ကေတ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ဖန်သားပြင်အပြည့်"</string>
<string name="desktop_text" msgid="1077633567027630454">"ဒက်စ်တော့မုဒ်"</string>
<string name="split_screen_text" msgid="1396336058129570886">"မျက်နှာပြင် ခွဲ၍ပြသရန်"</string>
<string name="more_button_text" msgid="3655388105592893530">"ပိုပြပါ"</string>
<string name="float_button_text" msgid="9221657008391364581">"မျှောရန်"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"ရွေးရန်"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ပိတ်ရန်"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"မီနူး ပိတ်ရန်"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index 7c96f0d681a8..6511567ce89d 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Lukk"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tilbake"</string>
<string name="handle_text" msgid="1766582106752184456">"Håndtak"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fullskjerm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Skrivebordmodus"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Delt skjerm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Svevende"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Velg"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skjermdump"</string>
+ <string name="close_text" msgid="4986518933445178928">"Lukk"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Lukk menyen"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index 8a89d4c2c05f..56bde827b112 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"बन्द गर्नुहोस्"</string>
<string name="back_button_text" msgid="1469718707134137085">"पछाडि"</string>
<string name="handle_text" msgid="1766582106752184456">"ह्यान्डल"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"एपको आइकन"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"फुल स्क्रिन"</string>
<string name="desktop_text" msgid="1077633567027630454">"डेस्कटप मोड"</string>
<string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रिन"</string>
<string name="more_button_text" msgid="3655388105592893530">"थप"</string>
<string name="float_button_text" msgid="9221657008391364581">"फ्लोट"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"चयन गर्नुहोस्"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"स्क्रिनसट"</string>
+ <string name="close_text" msgid="4986518933445178928">"बन्द गर्नुहोस्"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"मेनु बन्द गर्नुहोस्"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-night/colors.xml b/libs/WindowManager/Shell/res/values-night/colors.xml
index 83c4d93982f4..5c6bb57a7f1c 100644
--- a/libs/WindowManager/Shell/res/values-night/colors.xml
+++ b/libs/WindowManager/Shell/res/values-night/colors.xml
@@ -15,6 +15,7 @@
-->
<resources>
+ <color name="docked_divider_handle">#ffffff</color>
<!-- Bubbles -->
<color name="bubbles_icon_tint">@color/GM2_grey_200</color>
<!-- Splash screen-->
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index 1f0b6d233dcd..364774bb70b7 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Sluiten"</string>
<string name="back_button_text" msgid="1469718707134137085">"Terug"</string>
<string name="handle_text" msgid="1766582106752184456">"Gebruikersnaam"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"App-icoon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Volledig scherm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Gesplitst scherm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Meer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Zwevend"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Selecteren"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Sluiten"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menu sluiten"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index edfe3f01e6bc..59af0d975e2b 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ପଛକୁ ଫେରନ୍ତୁ"</string>
<string name="handle_text" msgid="1766582106752184456">"ହେଣ୍ଡେଲ"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"ଆପ ଆଇକନ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ପୂର୍ଣ୍ଣସ୍କ୍ରିନ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ଡେସ୍କଟପ ମୋଡ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ଅଧିକ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ଫ୍ଲୋଟ"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"ଚୟନ କରନ୍ତୁ"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ସ୍କ୍ରିନସଟ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ବନ୍ଦ କରନ୍ତୁ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ମେନୁ ବନ୍ଦ କରନ୍ତୁ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 8c2ad2231d19..a40c7e524755 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ਬੰਦ ਕਰੋ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ਪਿੱਛੇ"</string>
<string name="handle_text" msgid="1766582106752184456">"ਹੈਂਡਲ"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"ਐਪ ਪ੍ਰਤੀਕ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ਪੂਰੀ-ਸਕ੍ਰੀਨ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ਡੈਸਕਟਾਪ ਮੋਡ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ਹੋਰ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ਫ਼ਲੋਟ"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"ਚੁਣੋ"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ਬੰਦ ਕਰੋ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ਮੀਨੂ ਬੰਦ ਕਰੋ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index 191f6decebad..82ce6c9ab4bc 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zamknij"</string>
<string name="back_button_text" msgid="1469718707134137085">"Wstecz"</string>
<string name="handle_text" msgid="1766582106752184456">"Uchwyt"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacji"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pełny ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Tryb pulpitu"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Podzielony ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Więcej"</string>
<string name="float_button_text" msgid="9221657008391364581">"Pływające"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Wybierz"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Zrzut ekranu"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zamknij"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zamknij menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index 82409f40f8cf..ee9000b1fe17 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Voltar"</string>
<string name="handle_text" msgid="1766582106752184456">"Alça"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ícone do app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tela cheia"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo área de trabalho"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Tela dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mais"</string>
<string name="float_button_text" msgid="9221657008391364581">"Ponto flutuante"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Selecionar"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de tela"</string>
+ <string name="close_text" msgid="4986518933445178928">"Fechar"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index 82409f40f8cf..ee9000b1fe17 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Voltar"</string>
<string name="handle_text" msgid="1766582106752184456">"Alça"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ícone do app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tela cheia"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo área de trabalho"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Tela dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mais"</string>
<string name="float_button_text" msgid="9221657008391364581">"Ponto flutuante"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Selecionar"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de tela"</string>
+ <string name="close_text" msgid="4986518933445178928">"Fechar"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index 29297f4b55bd..afd3fe8f1696 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Închide"</string>
<string name="back_button_text" msgid="1469718707134137085">"Înapoi"</string>
<string name="handle_text" msgid="1766582106752184456">"Ghidaj"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Pictograma aplicației"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Ecran complet"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modul desktop"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Ecran împărțit"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mai multe"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotantă"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Selectează"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captură de ecran"</string>
+ <string name="close_text" msgid="4986518933445178928">"Închide"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Închide meniul"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index de0bcf4da82a..12481031ec83 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Закрыть"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Значок приложения"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Полноэкранный режим"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим компьютера"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Разделить экран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Ещё"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плавающее окно"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Выбрать"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Скриншот"</string>
+ <string name="close_text" msgid="4986518933445178928">"Закрыть"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Закрыть меню"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index 849dbac4c485..15d2c366cced 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"වසන්න"</string>
<string name="back_button_text" msgid="1469718707134137085">"ආපසු"</string>
<string name="handle_text" msgid="1766582106752184456">"හැඬලය"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"යෙදුම් නිරූපකය"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"පූර්ණ තිරය"</string>
<string name="desktop_text" msgid="1077633567027630454">"ඩෙස්ක්ටොප් ප්‍රකාරය"</string>
<string name="split_screen_text" msgid="1396336058129570886">"බෙදුම් තිරය"</string>
<string name="more_button_text" msgid="3655388105592893530">"තව"</string>
<string name="float_button_text" msgid="9221657008391364581">"පාවෙන"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"තෝරන්න"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"තිර රුව"</string>
+ <string name="close_text" msgid="4986518933445178928">"වසන්න"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"මෙනුව වසන්න"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index e86ecded8502..422c25def1f7 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zavrieť"</string>
<string name="back_button_text" msgid="1469718707134137085">"Späť"</string>
<string name="handle_text" msgid="1766582106752184456">"Rukoväť"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikácie"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Celá obrazovka"</string>
<string name="desktop_text" msgid="1077633567027630454">"Režim počítača"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Rozdelená obrazovka"</string>
<string name="more_button_text" msgid="3655388105592893530">"Viac"</string>
<string name="float_button_text" msgid="9221657008391364581">"Plávajúce"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Vybrať"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Snímka obrazovky"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zavrieť"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zavrieť ponuku"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index 954e7290163b..7096998769f4 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zapri"</string>
<string name="back_button_text" msgid="1469718707134137085">"Nazaj"</string>
<string name="handle_text" msgid="1766582106752184456">"Ročica"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Celozaslonsko"</string>
<string name="desktop_text" msgid="1077633567027630454">"Namizni način"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Razdeljen zaslon"</string>
<string name="more_button_text" msgid="3655388105592893530">"Več"</string>
<string name="float_button_text" msgid="9221657008391364581">"Lebdeče"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Izberi"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Posnetek zaslona"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zapri"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zapri meni"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index 6209ff912cde..3ef8b182b173 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Mbyll"</string>
<string name="back_button_text" msgid="1469718707134137085">"Pas"</string>
<string name="handle_text" msgid="1766582106752184456">"Emërtimi"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona e aplikacionit"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Ekrani i plotë"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modaliteti i desktopit"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Ekrani i ndarë"</string>
<string name="more_button_text" msgid="3655388105592893530">"Më shumë"</string>
<string name="float_button_text" msgid="9221657008391364581">"Pluskuese"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Zgjidh"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Pamja e ekranit"</string>
+ <string name="close_text" msgid="4986518933445178928">"Mbyll"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Mbyll menynë"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index f810d3d9890e..09c5ad1f22de 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Затворите"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Икона апликације"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Преко целог екрана"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим за рачунаре"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Подељени екран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Још"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плутајуће"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Изаберите"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Снимак екрана"</string>
+ <string name="close_text" msgid="4986518933445178928">"Затворите"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Затворите мени"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index 0e4487102f68..5bfa238f12be 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Stäng"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tillbaka"</string>
<string name="handle_text" msgid="1766582106752184456">"Handtag"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Helskärm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Datorläge"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Delad skärm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Svävande"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Välj"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skärmbild"</string>
+ <string name="close_text" msgid="4986518933445178928">"Stäng"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Stäng menyn"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index e167bcab1cdb..489d56e50a6c 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Funga"</string>
<string name="back_button_text" msgid="1469718707134137085">"Rudi nyuma"</string>
<string name="handle_text" msgid="1766582106752184456">"Ncha"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Aikoni ya Programu"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Skrini nzima"</string>
<string name="desktop_text" msgid="1077633567027630454">"Hali ya Kompyuta ya mezani"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Gawa Skrini"</string>
<string name="more_button_text" msgid="3655388105592893530">"Zaidi"</string>
<string name="float_button_text" msgid="9221657008391364581">"Inayoelea"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Chagua"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Picha ya skrini"</string>
+ <string name="close_text" msgid="4986518933445178928">"Funga"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Funga Menyu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index 286d60832db1..8a75b2140b65 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"மூடும்"</string>
<string name="back_button_text" msgid="1469718707134137085">"பின்செல்லும்"</string>
<string name="handle_text" msgid="1766582106752184456">"ஹேண்டில்"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"ஆப்ஸ் ஐகான்"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"முழுத்திரை"</string>
<string name="desktop_text" msgid="1077633567027630454">"டெஸ்க்டாப் பயன்முறை"</string>
<string name="split_screen_text" msgid="1396336058129570886">"திரையைப் பிரிக்கும்"</string>
<string name="more_button_text" msgid="3655388105592893530">"கூடுதல் விருப்பத்தேர்வுகள்"</string>
<string name="float_button_text" msgid="9221657008391364581">"மிதக்கும் சாளரம்"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"தேர்ந்தெடுக்கும்"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ஸ்கிரீன்ஷாட்"</string>
+ <string name="close_text" msgid="4986518933445178928">"மூடும்"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"மெனுவை மூடும்"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index ec3ca78cf747..d0e459ac622b 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"మూసివేయండి"</string>
<string name="back_button_text" msgid="1469718707134137085">"వెనుకకు"</string>
<string name="handle_text" msgid="1766582106752184456">"హ్యాండిల్"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"యాప్ చిహ్నం"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ఫుల్-స్క్రీన్"</string>
<string name="desktop_text" msgid="1077633567027630454">"డెస్క్‌టాప్ మోడ్"</string>
<string name="split_screen_text" msgid="1396336058129570886">"స్ప్లిట్ స్క్రీన్"</string>
<string name="more_button_text" msgid="3655388105592893530">"మరిన్ని"</string>
<string name="float_button_text" msgid="9221657008391364581">"ఫ్లోట్"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"ఎంచుకోండి"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"స్క్రీన్‌షాట్"</string>
+ <string name="close_text" msgid="4986518933445178928">"మూసివేయండి"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"మెనూను మూసివేయండి"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index 1a9fa1828cf5..2e926c42d07c 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ปิด"</string>
<string name="back_button_text" msgid="1469718707134137085">"กลับ"</string>
<string name="handle_text" msgid="1766582106752184456">"แฮนเดิล"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"ไอคอนแอป"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"เต็มหน้าจอ"</string>
<string name="desktop_text" msgid="1077633567027630454">"โหมดเดสก์ท็อป"</string>
<string name="split_screen_text" msgid="1396336058129570886">"แยกหน้าจอ"</string>
<string name="more_button_text" msgid="3655388105592893530">"เพิ่มเติม"</string>
<string name="float_button_text" msgid="9221657008391364581">"ล่องลอย"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"เลือก"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ภาพหน้าจอ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ปิด"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ปิดเมนู"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index 27c4363eb630..3db2507433c2 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Isara"</string>
<string name="back_button_text" msgid="1469718707134137085">"Bumalik"</string>
<string name="handle_text" msgid="1766582106752184456">"Handle"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Icon ng App"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Split Screen"</string>
<string name="more_button_text" msgid="3655388105592893530">"Higit pa"</string>
<string name="float_button_text" msgid="9221657008391364581">"Float"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Piliin"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Isara"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Isara ang Menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index a9ad92d39ec9..e43e4249b3b3 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Kapat"</string>
<string name="back_button_text" msgid="1469718707134137085">"Geri"</string>
<string name="handle_text" msgid="1766582106752184456">"Herkese açık kullanıcı adı"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Uygulama Simgesi"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Masaüstü Modu"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Bölünmüş Ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Daha Fazla"</string>
<string name="float_button_text" msgid="9221657008391364581">"Havada Süzülen"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Seç"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Ekran görüntüsü"</string>
+ <string name="close_text" msgid="4986518933445178928">"Kapat"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menüyü kapat"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index a9b05d513ec8..99f7e3027381 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Закрити"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Значок додатка"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"На весь екран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим комп’ютера"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Розділити екран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Більше"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плаваюче вікно"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Вибрати"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Знімок екрана"</string>
+ <string name="close_text" msgid="4986518933445178928">"Закрити"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Закрити меню"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 1c31a3dbbbe3..abab3e703306 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"بند کریں"</string>
<string name="back_button_text" msgid="1469718707134137085">"پیچھے"</string>
<string name="handle_text" msgid="1766582106752184456">"ہینڈل"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"ایپ کا آئیکن"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"مکمل اسکرین"</string>
<string name="desktop_text" msgid="1077633567027630454">"ڈیسک ٹاپ موڈ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"اسپلٹ اسکرین"</string>
<string name="more_button_text" msgid="3655388105592893530">"مزید"</string>
<string name="float_button_text" msgid="9221657008391364581">"فلوٹ"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"منتخب کریں"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"اسکرین شاٹ"</string>
+ <string name="close_text" msgid="4986518933445178928">"بند کریں"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"مینو بند کریں"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index 3ce167293d39..90f3c6062529 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Yopish"</string>
<string name="back_button_text" msgid="1469718707134137085">"Orqaga"</string>
<string name="handle_text" msgid="1766582106752184456">"Identifikator"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Ilova belgisi"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Butun ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop rejimi"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Ekranni ikkiga ajratish"</string>
<string name="more_button_text" msgid="3655388105592893530">"Yana"</string>
<string name="float_button_text" msgid="9221657008391364581">"Pufakli"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Tanlash"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skrinshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Yopish"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menyuni yopish"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 1bf967a69eae..535fee33fccb 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Đóng"</string>
<string name="back_button_text" msgid="1469718707134137085">"Quay lại"</string>
<string name="handle_text" msgid="1766582106752184456">"Xử lý"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Biểu tượng ứng dụng"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Toàn màn hình"</string>
<string name="desktop_text" msgid="1077633567027630454">"Chế độ máy tính"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Chia đôi màn hình"</string>
<string name="more_button_text" msgid="3655388105592893530">"Tuỳ chọn khác"</string>
<string name="float_button_text" msgid="9221657008391364581">"Nổi"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Chọn"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Ảnh chụp màn hình"</string>
+ <string name="close_text" msgid="4986518933445178928">"Đóng"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Đóng trình đơn"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index 3a8dd242246b..83f703d4a3b4 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"关闭"</string>
<string name="back_button_text" msgid="1469718707134137085">"返回"</string>
<string name="handle_text" msgid="1766582106752184456">"处理"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"应用图标"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全屏"</string>
<string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string>
<string name="split_screen_text" msgid="1396336058129570886">"分屏"</string>
<string name="more_button_text" msgid="3655388105592893530">"更多"</string>
<string name="float_button_text" msgid="9221657008391364581">"悬浮"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"选择"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"屏幕截图"</string>
+ <string name="close_text" msgid="4986518933445178928">"关闭"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"关闭菜单"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 112bd41c4f15..c83f65dfcd72 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
<string name="back_button_text" msgid="1469718707134137085">"返去"</string>
<string name="handle_text" msgid="1766582106752184456">"控點"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"應用程式圖示"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string>
<string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string>
<string name="split_screen_text" msgid="1396336058129570886">"分割螢幕"</string>
<string name="more_button_text" msgid="3655388105592893530">"更多"</string>
<string name="float_button_text" msgid="9221657008391364581">"浮動"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"選取"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"螢幕截圖"</string>
+ <string name="close_text" msgid="4986518933445178928">"關閉"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"關閉選單"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index edb0c7e8aa88..08df469186aa 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
<string name="back_button_text" msgid="1469718707134137085">"返回"</string>
<string name="handle_text" msgid="1766582106752184456">"控點"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"應用程式圖示"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string>
<string name="desktop_text" msgid="1077633567027630454">"電腦模式"</string>
<string name="split_screen_text" msgid="1396336058129570886">"分割畫面"</string>
<string name="more_button_text" msgid="3655388105592893530">"更多"</string>
<string name="float_button_text" msgid="9221657008391364581">"浮動"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"選取"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"螢幕截圖"</string>
+ <string name="close_text" msgid="4986518933445178928">"關閉"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"關閉選單"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index 749b223993db..9232b729b964 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -96,19 +96,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Vala"</string>
<string name="back_button_text" msgid="1469718707134137085">"Emuva"</string>
<string name="handle_text" msgid="1766582106752184456">"Isibambo"</string>
- <!-- no translation found for app_icon_text (2823268023931811747) -->
- <skip />
+ <string name="app_icon_text" msgid="2823268023931811747">"Isithonjana Se-app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Isikrini esigcwele"</string>
<string name="desktop_text" msgid="1077633567027630454">"Imodi Yedeskithophu"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Hlukanisa isikrini"</string>
<string name="more_button_text" msgid="3655388105592893530">"Okwengeziwe"</string>
<string name="float_button_text" msgid="9221657008391364581">"Iflowuthi"</string>
- <!-- no translation found for select_text (5139083974039906583) -->
- <skip />
- <!-- no translation found for screenshot_text (1477704010087786671) -->
- <skip />
- <!-- no translation found for close_text (4986518933445178928) -->
- <skip />
- <!-- no translation found for collapse_menu_text (7515008122450342029) -->
- <skip />
+ <string name="select_text" msgid="5139083974039906583">"Khetha"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Isithombe-skrini"</string>
+ <string name="close_text" msgid="4986518933445178928">"Vala"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Vala Imenyu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index 6e750a3d5e34..6fb70006e67f 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -17,7 +17,8 @@
*/
-->
<resources>
- <color name="docked_divider_handle">#ffffff</color>
+ <color name="docked_divider_handle">#000000</color>
+ <color name="split_divider_background">@color/taskbar_background</color>
<drawable name="forced_resizable_background">#59000000</drawable>
<color name="minimize_dock_shadow_start">#60000000</color>
<color name="minimize_dock_shadow_end">#00000000</color>
@@ -41,6 +42,9 @@
<color name="letterbox_education_accent_primary">@android:color/system_accent1_100</color>
<color name="letterbox_education_text_secondary">@android:color/system_neutral2_200</color>
+ <!-- Letterbox Dialog -->
+ <color name="letterbox_dialog_background">@android:color/system_neutral1_900</color>
+
<!-- GM2 colors -->
<color name="GM2_grey_200">#E8EAED</color>
<color name="GM2_grey_700">#5F6368</color>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 6f31d0674246..680ad5101366 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -273,6 +273,18 @@
<!-- The space between two actions in the letterbox education dialog -->
<dimen name="letterbox_education_dialog_space_between_actions">24dp</dimen>
+ <!-- The corner radius of the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_button_radius">12dp</dimen>
+
+ <!-- The horizontal padding for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_horizontal_padding">16dp</dimen>
+
+ <!-- The vertical padding for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_vertical_padding">8dp</dimen>
+
+ <!-- The insets for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_vertical_inset">6dp</dimen>
+
<!-- The margin between the dialog container and its parent. -->
<dimen name="letterbox_restart_dialog_margin">24dp</dimen>
@@ -306,6 +318,15 @@
<!-- The corner radius of the buttons in the restart dialog -->
<dimen name="letterbox_restart_dialog_button_radius">18dp</dimen>
+ <!-- The insets for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_vertical_inset">6dp</dimen>
+
+ <!-- The horizontal padding for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_horizontal_padding">16dp</dimen>
+
+ <!-- The vertical padding for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_vertical_padding">8dp</dimen>
+
<!-- The width of the brand image on staring surface. -->
<dimen name="starting_surface_brand_image_width">200dp</dimen>
@@ -331,30 +352,6 @@
-->
<dimen name="overridable_minimal_size_pip_resizable_task">48dp</dimen>
- <!-- The size of the drag handle / menu shown along with a floating task. -->
- <dimen name="floating_task_menu_size">32dp</dimen>
-
- <!-- The size of menu items in the floating task menu. -->
- <dimen name="floating_task_menu_item_size">24dp</dimen>
-
- <!-- The horizontal margin of menu items in the floating task menu. -->
- <dimen name="floating_task_menu_item_padding">5dp</dimen>
-
- <!-- The width of visible floating view region when stashed. -->
- <dimen name="floating_task_stash_offset">32dp</dimen>
-
- <!-- The amount of elevation for a floating task. -->
- <dimen name="floating_task_elevation">8dp</dimen>
-
- <!-- The amount of padding around the bottom and top of the task. -->
- <dimen name="floating_task_vertical_padding">8dp</dimen>
-
- <!-- The normal size of the dismiss target. -->
- <dimen name="floating_task_dismiss_circle_size">150dp</dimen>
-
- <!-- The smaller size of the dismiss target (shrinks when something is in the target). -->
- <dimen name="floating_dismiss_circle_small">120dp</dimen>
-
<!-- The thickness of shadows of a window that has focus in DIP. -->
<dimen name="freeform_decor_shadow_focused_thickness">20dp</dimen>
@@ -373,6 +370,10 @@
<dimen name="freeform_resize_corner">44dp</dimen>
- <dimen name="caption_menu_elevation">4dp</dimen>
+ <!-- The radius of the caption menu shadow. -->
+ <dimen name="caption_menu_shadow_radius">4dp</dimen>
+
+ <!-- The radius of the caption menu corners. -->
+ <dimen name="caption_menu_corner_radius">20dp</dimen>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index bae009a0526f..bc2e71d1c013 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -38,11 +38,9 @@
</style>
<style name="CaptionWindowingButtonStyle">
- <item name="android:layout_width">32dp</item>
- <item name="android:layout_height">32dp</item>
+ <item name="android:layout_width">40dp</item>
+ <item name="android:layout_height">40dp</item>
<item name="android:padding">4dp</item>
- <item name="android:layout_marginTop">5dp</item>
- <item name="android:layout_marginBottom">5dp</item>
</style>
<style name="CaptionMenuButtonStyle" parent="@style/Widget.AppCompat.Button.Borderless">
@@ -80,6 +78,12 @@
<item name="android:textColor">@color/tv_pip_edu_text</item>
</style>
+ <style name="LetterboxDialog" parent="@android:style/Theme.Holo">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:background">@color/letterbox_dialog_background</item>
+ </style>
+
<style name="RestartDialogTitleText">
<item name="android:textSize">24sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
@@ -87,6 +91,9 @@
<item name="android:textAppearance">
@*android:style/TextAppearance.DeviceDefault.Headline
</item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamilyMedium
+ </item>
</style>
<style name="RestartDialogBodyText">
@@ -97,24 +104,44 @@
<item name="android:textAppearance">
@*android:style/TextAppearance.DeviceDefault.Body2
</item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamily
+ </item>
</style>
<style name="RestartDialogCheckboxText">
<item name="android:textSize">16sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:lineSpacingExtra">4sp</item>
- <item name="android:textAppearance">@*android:style/TextAppearance.DeviceDefault</item>
+ <item name="android:textAppearance">
+ @*android:style/TextAppearance.DeviceDefault.Headline
+ </item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamilyMedium
+ </item>
</style>
<style name="RestartDialogDismissButton">
<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">
<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>
</resources>
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 71e15c12b9c0..541c0f04b9b9 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
@@ -61,6 +61,7 @@ import android.os.Binder;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.notification.NotificationListenerService;
@@ -125,6 +126,39 @@ public class BubbleController implements ConfigurationChangeListener {
private static final String SYSTEM_DIALOG_REASON_KEY = "reason";
private static final String SYSTEM_DIALOG_REASON_GESTURE_NAV = "gestureNav";
+ // TODO(b/256873975) Should use proper flag when available to shell/launcher
+ /**
+ * Whether bubbles are showing in the bubble bar from launcher. This is only available
+ * on large screens and {@link BubbleController#isShowingAsBubbleBar()} should be used
+ * to check all conditions that indicate if the bubble bar is in use.
+ */
+ private static final boolean BUBBLE_BAR_ENABLED =
+ SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false);
+
+
+ /**
+ * Common interface to send updates to bubble views.
+ */
+ public interface BubbleViewCallback {
+ /** Called when the provided bubble should be removed. */
+ void removeBubble(Bubble removedBubble);
+ /** Called when the provided bubble should be added. */
+ void addBubble(Bubble addedBubble);
+ /** Called when the provided bubble should be updated. */
+ void updateBubble(Bubble updatedBubble);
+ /** Called when the provided bubble should be selected. */
+ void selectionChanged(BubbleViewProvider selectedBubble);
+ /** Called when the provided bubble's suppression state has changed. */
+ void suppressionChanged(Bubble bubble, boolean isSuppressed);
+ /** Called when the expansion state of bubbles has changed. */
+ void expansionChanged(boolean isExpanded);
+ /**
+ * Called when the order of the bubble list has changed. Depending on the expanded state
+ * the pointer might need to be updated.
+ */
+ void bubbleOrderChanged(List<Bubble> bubbleOrder, boolean updatePointer);
+ }
+
private final Context mContext;
private final BubblesImpl mImpl = new BubblesImpl();
private Bubbles.BubbleExpandListener mExpandListener;
@@ -147,12 +181,8 @@ public class BubbleController implements ConfigurationChangeListener {
// Used to post to main UI thread
private final ShellExecutor mMainExecutor;
private final Handler mMainHandler;
-
private final ShellExecutor mBackgroundExecutor;
- // Whether or not we should show bubbles pinned at the bottom of the screen.
- private boolean mIsBubbleBarEnabled;
-
private BubbleLogger mLogger;
private BubbleData mBubbleData;
@Nullable private BubbleStackView mStackView;
@@ -533,10 +563,10 @@ public class BubbleController implements ConfigurationChangeListener {
mDataRepository.removeBubblesForUser(removedUserId, parentUserId);
}
- // TODO(b/256873975): Should pass this into the constructor once flags are available to shell.
- /** Sets whether the bubble bar is enabled (i.e. bubbles pinned to bottom on large screens). */
- public void setBubbleBarEnabled(boolean enabled) {
- mIsBubbleBarEnabled = enabled;
+ /** Whether bubbles are showing in the bubble bar. */
+ public boolean isShowingAsBubbleBar() {
+ // TODO(b/269670598): should also check that we're in gesture nav
+ return BUBBLE_BAR_ENABLED && mBubblePositioner.isLargeScreen();
}
/** Whether this userId belongs to the current user. */
@@ -605,12 +635,6 @@ public class BubbleController implements ConfigurationChangeListener {
mStackView.setUnbubbleConversationCallback(mSysuiProxy::onUnbubbleConversation);
}
- if (mIsBubbleBarEnabled && mBubblePositioner.isLargeScreen()) {
- mBubblePositioner.setUsePinnedLocation(true);
- } else {
- mBubblePositioner.setUsePinnedLocation(false);
- }
-
addToWindowManagerMaybe();
}
@@ -1284,6 +1308,58 @@ public class BubbleController implements ConfigurationChangeListener {
});
}
+ private final BubbleViewCallback mBubbleViewCallback = new BubbleViewCallback() {
+ @Override
+ public void removeBubble(Bubble removedBubble) {
+ if (mStackView != null) {
+ mStackView.removeBubble(removedBubble);
+ }
+ }
+
+ @Override
+ public void addBubble(Bubble addedBubble) {
+ if (mStackView != null) {
+ mStackView.addBubble(addedBubble);
+ }
+ }
+
+ @Override
+ public void updateBubble(Bubble updatedBubble) {
+ if (mStackView != null) {
+ mStackView.updateBubble(updatedBubble);
+ }
+ }
+
+ @Override
+ public void bubbleOrderChanged(List<Bubble> bubbleOrder, boolean updatePointer) {
+ if (mStackView != null) {
+ mStackView.updateBubbleOrder(bubbleOrder, updatePointer);
+ }
+ }
+
+ @Override
+ public void suppressionChanged(Bubble bubble, boolean isSuppressed) {
+ if (mStackView != null) {
+ mStackView.setBubbleSuppressed(bubble, isSuppressed);
+ }
+ }
+
+ @Override
+ public void expansionChanged(boolean isExpanded) {
+ if (mStackView != null) {
+ mStackView.setExpanded(isExpanded);
+ }
+ }
+
+ @Override
+ public void selectionChanged(BubbleViewProvider selectedBubble) {
+ if (mStackView != null) {
+ mStackView.setSelectedBubble(selectedBubble);
+ }
+
+ }
+ };
+
@SuppressWarnings("FieldCanBeLocal")
private final BubbleData.Listener mBubbleDataListener = new BubbleData.Listener() {
@@ -1306,7 +1382,8 @@ public class BubbleController implements ConfigurationChangeListener {
// Lazy load overflow bubbles from disk
loadOverflowBubblesFromDisk();
- mStackView.updateOverflowButtonDot();
+ // If bubbles in the overflow have a dot, make sure the overflow shows a dot
+ updateOverflowButtonDot();
// Update bubbles in overflow.
if (mOverflowListener != null) {
@@ -1321,9 +1398,7 @@ public class BubbleController implements ConfigurationChangeListener {
final Bubble bubble = removed.first;
@Bubbles.DismissReason final int reason = removed.second;
- if (mStackView != null) {
- mStackView.removeBubble(bubble);
- }
+ mBubbleViewCallback.removeBubble(bubble);
// Leave the notification in place if we're dismissing due to user switching, or
// because DND is suppressing the bubble. In both of those cases, we need to be able
@@ -1353,49 +1428,47 @@ public class BubbleController implements ConfigurationChangeListener {
}
mDataRepository.removeBubbles(mCurrentUserId, bubblesToBeRemovedFromRepository);
- if (update.addedBubble != null && mStackView != null) {
+ if (update.addedBubble != null) {
mDataRepository.addBubble(mCurrentUserId, update.addedBubble);
- mStackView.addBubble(update.addedBubble);
+ mBubbleViewCallback.addBubble(update.addedBubble);
}
- if (update.updatedBubble != null && mStackView != null) {
- mStackView.updateBubble(update.updatedBubble);
+ if (update.updatedBubble != null) {
+ mBubbleViewCallback.updateBubble(update.updatedBubble);
}
- if (update.suppressedBubble != null && mStackView != null) {
- mStackView.setBubbleSuppressed(update.suppressedBubble, true);
+ if (update.suppressedBubble != null) {
+ mBubbleViewCallback.suppressionChanged(update.suppressedBubble, true);
}
- if (update.unsuppressedBubble != null && mStackView != null) {
- mStackView.setBubbleSuppressed(update.unsuppressedBubble, false);
+ if (update.unsuppressedBubble != null) {
+ mBubbleViewCallback.suppressionChanged(update.unsuppressedBubble, false);
}
boolean collapseStack = update.expandedChanged && !update.expanded;
// At this point, the correct bubbles are inflated in the stack.
// Make sure the order in bubble data is reflected in bubble row.
- if (update.orderChanged && mStackView != null) {
+ if (update.orderChanged) {
mDataRepository.addBubbles(mCurrentUserId, update.bubbles);
// if the stack is going to be collapsed, do not update pointer position
// after reordering
- mStackView.updateBubbleOrder(update.bubbles, !collapseStack);
+ mBubbleViewCallback.bubbleOrderChanged(update.bubbles, !collapseStack);
}
if (collapseStack) {
- mStackView.setExpanded(false);
+ mBubbleViewCallback.expansionChanged(/* expanded= */ false);
mSysuiProxy.requestNotificationShadeTopUi(false, TAG);
}
- if (update.selectionChanged && mStackView != null) {
- mStackView.setSelectedBubble(update.selectedBubble);
+ if (update.selectionChanged) {
+ mBubbleViewCallback.selectionChanged(update.selectedBubble);
}
// Expanding? Apply this last.
if (update.expandedChanged && update.expanded) {
- if (mStackView != null) {
- mStackView.setExpanded(true);
- mSysuiProxy.requestNotificationShadeTopUi(true, TAG);
- }
+ mBubbleViewCallback.expansionChanged(/* expanded= */ true);
+ mSysuiProxy.requestNotificationShadeTopUi(true, TAG);
}
mSysuiProxy.notifyInvalidateNotifications("BubbleData.Listener.applyUpdate");
@@ -1406,6 +1479,19 @@ public class BubbleController implements ConfigurationChangeListener {
}
};
+ private void updateOverflowButtonDot() {
+ BubbleOverflow overflow = mBubbleData.getOverflow();
+ if (overflow == null) return;
+
+ for (Bubble b : mBubbleData.getOverflowBubbles()) {
+ if (b.showDot()) {
+ overflow.setShowDot(true);
+ return;
+ }
+ }
+ overflow.setShowDot(false);
+ }
+
private boolean handleDismissalInterception(BubbleEntry entry,
@Nullable List<BubbleEntry> children, IntConsumer removeCallback) {
if (isSummaryOfBubbles(entry)) {
@@ -1852,13 +1938,6 @@ public class BubbleController implements ConfigurationChangeListener {
}
@Override
- public void setBubbleBarEnabled(boolean enabled) {
- mMainExecutor.execute(() -> {
- BubbleController.this.setBubbleBarEnabled(enabled);
- });
- }
-
- @Override
public void onNotificationPanelExpandedChanged(boolean expanded) {
mMainExecutor.execute(
() -> BubbleController.this.onNotificationPanelExpandedChanged(expanded));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index 6230d22ebe12..3fd09675a245 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -283,7 +283,7 @@ public class BubbleData {
}
boolean isShowingOverflow() {
- return mShowingOverflow && (isExpanded() || mPositioner.showingInTaskbar());
+ return mShowingOverflow && isExpanded();
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index 07c58527a815..5ea2450114f0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -18,9 +18,6 @@ package com.android.wm.shell.bubbles;
import static android.view.View.LAYOUT_DIRECTION_RTL;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.annotation.IntDef;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -39,8 +36,6 @@ import androidx.annotation.VisibleForTesting;
import com.android.launcher3.icons.IconNormalizer;
import com.android.wm.shell.R;
-import java.lang.annotation.Retention;
-
/**
* Keeps track of display size, configuration, and specific bubble sizes. One place for all
* placement and positioning calculations to refer to.
@@ -50,15 +45,6 @@ public class BubblePositioner {
? "BubblePositioner"
: BubbleDebugConfig.TAG_BUBBLES;
- @Retention(SOURCE)
- @IntDef({TASKBAR_POSITION_NONE, TASKBAR_POSITION_RIGHT, TASKBAR_POSITION_LEFT,
- TASKBAR_POSITION_BOTTOM})
- @interface TaskbarPosition {}
- public static final int TASKBAR_POSITION_NONE = -1;
- public static final int TASKBAR_POSITION_RIGHT = 0;
- public static final int TASKBAR_POSITION_LEFT = 1;
- public static final int TASKBAR_POSITION_BOTTOM = 2;
-
/** When the bubbles are collapsed in a stack only some of them are shown, this is how many. **/
public static final int NUM_VISIBLE_WHEN_RESTING = 2;
/** Indicates a bubble's height should be the maximum available space. **/
@@ -108,15 +94,9 @@ public class BubblePositioner {
private int mOverflowHeight;
private int mMinimumFlyoutWidthLargeScreen;
- private PointF mPinLocation;
private PointF mRestingStackPosition;
private int[] mPaddings = new int[4];
- private boolean mShowingInTaskbar;
- private @TaskbarPosition int mTaskbarPosition = TASKBAR_POSITION_NONE;
- private int mTaskbarIconSize;
- private int mTaskbarSize;
-
public BubblePositioner(Context context, WindowManager windowManager) {
mContext = context;
mWindowManager = windowManager;
@@ -153,27 +133,11 @@ public class BubblePositioner {
+ " insets: " + insets
+ " isLargeScreen: " + mIsLargeScreen
+ " isSmallTablet: " + mIsSmallTablet
- + " bounds: " + bounds
- + " showingInTaskbar: " + mShowingInTaskbar);
+ + " bounds: " + bounds);
}
updateInternal(mRotation, insets, bounds);
}
- /**
- * Updates position information to account for taskbar state.
- *
- * @param taskbarPosition which position the taskbar is displayed in.
- * @param showingInTaskbar whether the taskbar is being shown.
- */
- public void updateForTaskbar(int iconSize,
- @TaskbarPosition int taskbarPosition, boolean showingInTaskbar, int taskbarSize) {
- mShowingInTaskbar = showingInTaskbar;
- mTaskbarIconSize = iconSize;
- mTaskbarPosition = taskbarPosition;
- mTaskbarSize = taskbarSize;
- update();
- }
-
@VisibleForTesting
public void updateInternal(int rotation, Insets insets, Rect bounds) {
mRotation = rotation;
@@ -232,10 +196,6 @@ public class BubblePositioner {
R.dimen.bubbles_flyout_min_width_large_screen);
mMaxBubbles = calculateMaxBubbles();
-
- if (mShowingInTaskbar) {
- adjustForTaskbar();
- }
}
/**
@@ -260,30 +220,6 @@ public class BubblePositioner {
return mDefaultMaxBubbles;
}
- /**
- * Taskbar insets appear as navigationBar insets, however, unlike navigationBar this should
- * not inset bubbles UI as bubbles floats above the taskbar. This adjust the available space
- * and insets to account for the taskbar.
- */
- // TODO(b/171559950): When the insets are reported correctly we can remove this logic
- private void adjustForTaskbar() {
- // When bar is showing on edges... subtract that inset because we appear on top
- if (mShowingInTaskbar && mTaskbarPosition != TASKBAR_POSITION_BOTTOM) {
- WindowInsets metricInsets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
- Insets navBarInsets = metricInsets.getInsetsIgnoringVisibility(
- WindowInsets.Type.navigationBars());
- int newInsetLeft = mInsets.left;
- int newInsetRight = mInsets.right;
- if (mTaskbarPosition == TASKBAR_POSITION_LEFT) {
- mPositionRect.left -= navBarInsets.left;
- newInsetLeft -= navBarInsets.left;
- } else if (mTaskbarPosition == TASKBAR_POSITION_RIGHT) {
- mPositionRect.right += navBarInsets.right;
- newInsetRight -= navBarInsets.right;
- }
- mInsets = Insets.of(newInsetLeft, mInsets.top, newInsetRight, mInsets.bottom);
- }
- }
/**
* @return a rect of available screen space accounting for orientation, system bars and cutouts.
@@ -327,14 +263,12 @@ public class BubblePositioner {
* to the left or right side.
*/
public boolean showBubblesVertically() {
- return isLandscape() || mShowingInTaskbar || mIsLargeScreen;
+ return isLandscape() || mIsLargeScreen;
}
/** Size of the bubble. */
public int getBubbleSize() {
- return (mShowingInTaskbar && mTaskbarIconSize > 0)
- ? mTaskbarIconSize
- : mBubbleSize;
+ return mBubbleSize;
}
/** The amount of padding at the top of the screen that the bubbles avoid when being placed. */
@@ -699,9 +633,6 @@ public class BubblePositioner {
/** The position the bubble stack should rest at when collapsed. */
public PointF getRestingPosition() {
- if (mPinLocation != null) {
- return mPinLocation;
- }
if (mRestingStackPosition == null) {
return getDefaultStartPosition();
}
@@ -713,9 +644,6 @@ public class BubblePositioner {
* is being shown.
*/
public PointF getDefaultStartPosition() {
- if (mPinLocation != null) {
- return mPinLocation;
- }
// Start on the left if we're in LTR, right otherwise.
final boolean startOnLeft =
mContext.getResources().getConfiguration().getLayoutDirection()
@@ -730,7 +658,6 @@ public class BubblePositioner {
1 /* default starts with 1 bubble */));
}
-
/**
* Returns the region that the stack position must stay within. This goes slightly off the left
* and right sides of the screen, below the status bar/cutout and above the navigation bar.
@@ -751,39 +678,6 @@ public class BubblePositioner {
}
/**
- * @return whether the bubble stack is pinned to the taskbar.
- */
- public boolean showingInTaskbar() {
- return mShowingInTaskbar;
- }
-
- /**
- * @return the taskbar position if set.
- */
- public int getTaskbarPosition() {
- return mTaskbarPosition;
- }
-
- public int getTaskbarSize() {
- return mTaskbarSize;
- }
-
- /**
- * In some situations bubbles will be pinned to a specific onscreen location. This sets whether
- * bubbles should be pinned or not.
- */
- public void setUsePinnedLocation(boolean usePinnedLocation) {
- if (usePinnedLocation) {
- mShowingInTaskbar = true;
- mPinLocation = new PointF(mPositionRect.right - mBubbleSize,
- mPositionRect.bottom - mBubbleSize);
- } else {
- mPinLocation = null;
- mShowingInTaskbar = false;
- }
- }
-
- /**
* Navigation bar has an area where system gestures can be started from.
*
* @return {@link Rect} for system navigation bar gesture zone
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index f2afefe243bc..5ecbd6b596b6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -680,8 +680,6 @@ public class BubbleStackView extends FrameLayout
// Re-show the expanded view if we hid it.
showExpandedViewIfNeeded();
- } else if (mPositioner.showingInTaskbar()) {
- mStackAnimationController.snapStackBack();
} else {
// Fling the stack to the edge, and save whether or not it's going to end up on
// the left side of the screen.
@@ -1362,16 +1360,6 @@ public class BubbleStackView extends FrameLayout
updateOverflowVisibility();
}
- void updateOverflowButtonDot() {
- for (Bubble b : mBubbleData.getOverflowBubbles()) {
- if (b.showDot()) {
- mBubbleOverflow.setShowDot(true);
- return;
- }
- }
- mBubbleOverflow.setShowDot(false);
- }
-
/**
* Handle theme changes.
*/
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 df4325763a17..a5deac5a51da 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
@@ -257,11 +257,6 @@ public interface Bubbles {
*/
void onUserRemoved(int removedUserId);
- /**
- * Sets whether bubble bar should be enabled or not.
- */
- void setBubbleBarEnabled(boolean enabled);
-
/** Listener to find out about stack expansion / collapse events. */
interface BubbleExpandListener {
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
index 0ee0ea60a1bc..5533842f2d89 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
@@ -417,23 +417,9 @@ public class StackAnimationController extends
}
/**
- * Snaps the stack back to the previous resting position.
- */
- public void snapStackBack() {
- if (mLayout == null) {
- return;
- }
- PointF p = getStackPositionAlongNearestHorizontalEdge();
- springStackAfterFling(p.x, p.y);
- }
-
- /**
* Where the stack would be if it were snapped to the nearest horizontal edge (left or right).
*/
public PointF getStackPositionAlongNearestHorizontalEdge() {
- if (mPositioner.showingInTaskbar()) {
- return mPositioner.getRestingPosition();
- }
final PointF stackPos = getStackPosition();
final boolean onLeft = mLayout.isFirstChildXLeftOfCenter(stackPos.x);
final RectF bounds = mPositioner.getAllowableStackPositionRegion(getBubbleCount());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java
new file mode 100644
index 000000000000..8b4ac1a8dc79
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.devicestate.DeviceStateManager;
+import android.util.SparseIntArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.wm.shell.sysui.ShellInit;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Wrapper class to track the device posture change on Fold-ables.
+ * See also <a
+ * href="https://developer.android.com/guide/topics/large-screens/learn-about-foldables
+ * #foldable_postures">Foldable states and postures</a> for reference.
+ *
+ * Note that most of the implementation here inherits from
+ * {@link com.android.systemui.statusbar.policy.DevicePostureController}.
+ *
+ * Use the {@link TabletopModeController} if you are interested in tabletop mode change only,
+ * which is more common.
+ */
+public class DevicePostureController {
+ @IntDef(prefix = {"DEVICE_POSTURE_"}, value = {
+ DEVICE_POSTURE_UNKNOWN,
+ DEVICE_POSTURE_CLOSED,
+ DEVICE_POSTURE_HALF_OPENED,
+ DEVICE_POSTURE_OPENED,
+ DEVICE_POSTURE_FLIPPED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DevicePostureInt {}
+
+ // NOTE: These constants **must** match those defined for Jetpack Sidecar. This is because we
+ // use the Device State -> Jetpack Posture map to translate between the two.
+ public static final int DEVICE_POSTURE_UNKNOWN = 0;
+ public static final int DEVICE_POSTURE_CLOSED = 1;
+ public static final int DEVICE_POSTURE_HALF_OPENED = 2;
+ public static final int DEVICE_POSTURE_OPENED = 3;
+ public static final int DEVICE_POSTURE_FLIPPED = 4;
+
+ private final Context mContext;
+ private final ShellExecutor mMainExecutor;
+ private final List<OnDevicePostureChangedListener> mListeners = new ArrayList<>();
+ private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray();
+
+ private int mDevicePosture = DEVICE_POSTURE_UNKNOWN;
+
+ public DevicePostureController(
+ Context context, ShellInit shellInit, ShellExecutor mainExecutor) {
+ mContext = context;
+ mMainExecutor = mainExecutor;
+ shellInit.addInitCallback(this::onInit, this);
+ }
+
+ private void onInit() {
+ // Most of this is borrowed from WindowManager/Jetpack/DeviceStateManagerPostureProducer.
+ // Using the sidecar/extension libraries directly brings in a new dependency that it'd be
+ // good to avoid (along with the fact that sidecar is deprecated, and extensions isn't fully
+ // ready yet), and we'd have to make our own layer over the sidecar library anyway to easily
+ // allow the implementation to change, so it was easier to just interface with
+ // DeviceStateManager directly.
+ String[] deviceStatePosturePairs = mContext.getResources()
+ .getStringArray(R.array.config_device_state_postures);
+ for (String deviceStatePosturePair : deviceStatePosturePairs) {
+ String[] deviceStatePostureMapping = deviceStatePosturePair.split(":");
+ if (deviceStatePostureMapping.length != 2) {
+ continue;
+ }
+
+ int deviceState;
+ int posture;
+ try {
+ deviceState = Integer.parseInt(deviceStatePostureMapping[0]);
+ posture = Integer.parseInt(deviceStatePostureMapping[1]);
+ } catch (NumberFormatException e) {
+ continue;
+ }
+
+ mDeviceStateToPostureMap.put(deviceState, posture);
+ }
+
+ final DeviceStateManager deviceStateManager = mContext.getSystemService(
+ DeviceStateManager.class);
+ if (deviceStateManager != null) {
+ deviceStateManager.registerCallback(mMainExecutor, state -> onDevicePostureChanged(
+ mDeviceStateToPostureMap.get(state, DEVICE_POSTURE_UNKNOWN)));
+ }
+ }
+
+ @VisibleForTesting
+ void onDevicePostureChanged(int devicePosture) {
+ if (devicePosture == mDevicePosture) return;
+ mDevicePosture = devicePosture;
+ mListeners.forEach(l -> l.onDevicePostureChanged(mDevicePosture));
+ }
+
+ /**
+ * Register {@link OnDevicePostureChangedListener} for device posture changes.
+ * The listener will receive callback with current device posture upon registration.
+ */
+ public void registerOnDevicePostureChangedListener(
+ @NonNull OnDevicePostureChangedListener listener) {
+ if (mListeners.contains(listener)) return;
+ mListeners.add(listener);
+ listener.onDevicePostureChanged(mDevicePosture);
+ }
+
+ /**
+ * Unregister {@link OnDevicePostureChangedListener} for device posture changes.
+ */
+ public void unregisterOnDevicePostureChangedListener(
+ @NonNull OnDevicePostureChangedListener listener) {
+ mListeners.remove(listener);
+ }
+
+ /**
+ * Listener interface for device posture change.
+ */
+ public interface OnDevicePostureChangedListener {
+ /**
+ * Callback when device posture changes.
+ * See {@link DevicePostureInt} for callback values.
+ */
+ void onDevicePostureChanged(@DevicePostureInt int posture);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TabletopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TabletopModeController.java
new file mode 100644
index 000000000000..bf226283ae54
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TabletopModeController.java
@@ -0,0 +1,208 @@
+/*
+ * 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.wm.shell.common;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_HALF_OPENED;
+import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_UNKNOWN;
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_FOLDABLE;
+
+import android.annotation.NonNull;
+import android.app.WindowConfiguration;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.util.ArraySet;
+import android.view.Surface;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.annotations.ShellMainThread;
+import com.android.wm.shell.sysui.ShellInit;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Wrapper class to track the tabletop (aka. flex) mode change on Fold-ables.
+ * See also <a
+ * href="https://developer.android.com/guide/topics/large-screens/learn-about-foldables
+ * #foldable_postures">Foldable states and postures</a> for reference.
+ *
+ * Use the {@link DevicePostureController} for more detailed posture changes.
+ */
+public class TabletopModeController implements
+ DevicePostureController.OnDevicePostureChangedListener,
+ DisplayController.OnDisplaysChangedListener {
+ private static final long TABLETOP_MODE_DELAY_MILLIS = 1_000;
+
+ private final Context mContext;
+
+ private final DevicePostureController mDevicePostureController;
+
+ private final DisplayController mDisplayController;
+
+ private final ShellExecutor mMainExecutor;
+
+ private final Set<Integer> mTabletopModeRotations = new ArraySet<>();
+
+ private final List<OnTabletopModeChangedListener> mListeners = new ArrayList<>();
+
+ @VisibleForTesting
+ final Runnable mOnEnterTabletopModeCallback = () -> {
+ if (isInTabletopMode()) {
+ // We are still in tabletop mode, go ahead.
+ mayBroadcastOnTabletopModeChange(true /* isInTabletopMode */);
+ }
+ };
+
+ @DevicePostureController.DevicePostureInt
+ private int mDevicePosture = DEVICE_POSTURE_UNKNOWN;
+
+ @Surface.Rotation
+ private int mDisplayRotation = WindowConfiguration.ROTATION_UNDEFINED;
+
+ /**
+ * Track the last callback value for {@link OnTabletopModeChangedListener}.
+ * This is to avoid duplicated {@code false} callback to {@link #mListeners}.
+ */
+ private Boolean mLastIsInTabletopModeForCallback;
+
+ public TabletopModeController(Context context,
+ ShellInit shellInit,
+ DevicePostureController postureController,
+ DisplayController displayController,
+ @ShellMainThread ShellExecutor mainExecutor) {
+ mContext = context;
+ mDevicePostureController = postureController;
+ mDisplayController = displayController;
+ mMainExecutor = mainExecutor;
+ shellInit.addInitCallback(this::onInit, this);
+ }
+
+ @VisibleForTesting
+ void onInit() {
+ mDevicePostureController.registerOnDevicePostureChangedListener(this);
+ mDisplayController.addDisplayWindowListener(this);
+ // Aligns with what's in {@link com.android.server.wm.DisplayRotation}.
+ final int[] deviceTabletopRotations = mContext.getResources().getIntArray(
+ com.android.internal.R.array.config_deviceTabletopRotations);
+ if (deviceTabletopRotations == null || deviceTabletopRotations.length == 0) {
+ ProtoLog.e(WM_SHELL_FOLDABLE,
+ "No valid config_deviceTabletopRotations, can not tell"
+ + " tabletop mode in WMShell");
+ return;
+ }
+ for (int angle : deviceTabletopRotations) {
+ switch (angle) {
+ case 0:
+ mTabletopModeRotations.add(Surface.ROTATION_0);
+ break;
+ case 90:
+ mTabletopModeRotations.add(Surface.ROTATION_90);
+ break;
+ case 180:
+ mTabletopModeRotations.add(Surface.ROTATION_180);
+ break;
+ case 270:
+ mTabletopModeRotations.add(Surface.ROTATION_270);
+ break;
+ default:
+ ProtoLog.e(WM_SHELL_FOLDABLE,
+ "Invalid surface rotation angle in "
+ + "config_deviceTabletopRotations: %d",
+ angle);
+ break;
+ }
+ }
+ }
+
+ /** Register {@link OnTabletopModeChangedListener} to listen for tabletop mode change. */
+ public void registerOnTabletopModeChangedListener(
+ @NonNull OnTabletopModeChangedListener listener) {
+ if (listener == null || mListeners.contains(listener)) return;
+ mListeners.add(listener);
+ listener.onTabletopModeChanged(isInTabletopMode());
+ }
+
+ /** Unregister {@link OnTabletopModeChangedListener} for tabletop mode change. */
+ public void unregisterOnTabletopModeChangedListener(
+ @NonNull OnTabletopModeChangedListener listener) {
+ mListeners.remove(listener);
+ }
+
+ @Override
+ public void onDevicePostureChanged(@DevicePostureController.DevicePostureInt int posture) {
+ if (mDevicePosture != posture) {
+ onDevicePostureOrDisplayRotationChanged(posture, mDisplayRotation);
+ }
+ }
+
+ @Override
+ public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
+ final int newDisplayRotation = newConfig.windowConfiguration.getDisplayRotation();
+ if (displayId == DEFAULT_DISPLAY && newDisplayRotation != mDisplayRotation) {
+ onDevicePostureOrDisplayRotationChanged(mDevicePosture, newDisplayRotation);
+ }
+ }
+
+ private void onDevicePostureOrDisplayRotationChanged(
+ @DevicePostureController.DevicePostureInt int newPosture,
+ @Surface.Rotation int newDisplayRotation) {
+ final boolean wasInTabletopMode = isInTabletopMode();
+ mDevicePosture = newPosture;
+ mDisplayRotation = newDisplayRotation;
+ final boolean couldBeInTabletopMode = isInTabletopMode();
+ mMainExecutor.removeCallbacks(mOnEnterTabletopModeCallback);
+ if (!wasInTabletopMode && couldBeInTabletopMode) {
+ // May enter tabletop mode, but we need to wait for additional time since this
+ // could be an intermediate state.
+ mMainExecutor.executeDelayed(mOnEnterTabletopModeCallback, TABLETOP_MODE_DELAY_MILLIS);
+ } else {
+ // Cancel entering tabletop mode if any condition's changed.
+ mayBroadcastOnTabletopModeChange(false /* isInTabletopMode */);
+ }
+ }
+
+ private boolean isHalfOpened(@DevicePostureController.DevicePostureInt int posture) {
+ return posture == DEVICE_POSTURE_HALF_OPENED;
+ }
+
+ private boolean isInTabletopMode() {
+ return isHalfOpened(mDevicePosture) && mTabletopModeRotations.contains(mDisplayRotation);
+ }
+
+ private void mayBroadcastOnTabletopModeChange(boolean isInTabletopMode) {
+ if (mLastIsInTabletopModeForCallback == null
+ || mLastIsInTabletopModeForCallback != isInTabletopMode) {
+ mListeners.forEach(l -> l.onTabletopModeChanged(isInTabletopMode));
+ mLastIsInTabletopModeForCallback = isInTabletopMode;
+ }
+ }
+
+ /**
+ * Listener interface for tabletop mode change.
+ */
+ public interface OnTabletopModeChangedListener {
+ /**
+ * Callback when tabletop mode changes. Expect duplicated callbacks with {@code false}.
+ * @param isInTabletopMode {@code true} if enters tabletop mode, {@code false} otherwise.
+ */
+ void onTabletopModeChanged(boolean isInTabletopMode);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index abb357c5b653..bdf0ac2ed30c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -247,11 +247,11 @@ public class SplitDecorManager extends WindowlessWindowManager {
/** Stops showing resizing hint. */
public void onResized(SurfaceControl.Transaction t, Runnable animFinishedCallback) {
- if (mScreenshot != null) {
- if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
- mScreenshotAnimator.cancel();
- }
+ if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
+ mScreenshotAnimator.cancel();
+ }
+ if (mScreenshot != null) {
t.setPosition(mScreenshot, mOffsetX, mOffsetY);
final SurfaceControl.Transaction animT = new SurfaceControl.Transaction();
@@ -321,6 +321,10 @@ public class SplitDecorManager extends WindowlessWindowManager {
/** Screenshot host leash and attach on it if meet some conditions */
public void screenshotIfNeeded(SurfaceControl.Transaction t) {
if (!mShown && mIsResizing && !mOldBounds.equals(mResizingBounds)) {
+ if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
+ mScreenshotAnimator.cancel();
+ }
+
mTempRect.set(mOldBounds);
mTempRect.offsetTo(0, 0);
mScreenshot = ScreenshotUtils.takeScreenshot(t, mHostLeash, mTempRect,
@@ -333,6 +337,10 @@ public class SplitDecorManager extends WindowlessWindowManager {
if (screenshot == null || !screenshot.isValid()) return;
if (!mShown && mIsResizing && !mOldBounds.equals(mResizingBounds)) {
+ if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
+ mScreenshotAnimator.cancel();
+ }
+
mScreenshot = screenshot;
t.reparent(screenshot, mHostLeash);
t.setLayer(screenshot, Integer.MAX_VALUE - 1);
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 f616e6f64750..ffc56b6f6106 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
@@ -120,6 +120,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
private int mOrientation;
private int mRotation;
private int mDensity;
+ private int mUiMode;
private final boolean mDimNonImeSide;
private ValueAnimator mDividerFlingAnimator;
@@ -295,10 +296,12 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
final Rect rootBounds = configuration.windowConfiguration.getBounds();
final int orientation = configuration.orientation;
final int density = configuration.densityDpi;
+ final int uiMode = configuration.uiMode;
if (mOrientation == orientation
&& mRotation == rotation
&& mDensity == density
+ && mUiMode == uiMode
&& mRootBounds.equals(rootBounds)) {
return false;
}
@@ -310,6 +313,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
mRootBounds.set(rootBounds);
mRotation = rotation;
mDensity = density;
+ mUiMode = uiMode;
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
updateDividerConfig(mContext);
initDividerPosition(mTempRect);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index 3b2db5127316..76d9152fdfbc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -126,14 +126,12 @@ public class CompatUIController implements OnDisplaysChangedListener,
private final Lazy<Transitions> mTransitionsLazy;
private final DockStateReader mDockStateReader;
private final CompatUIConfiguration mCompatUIConfiguration;
-
- private CompatUICallback mCallback;
-
// Only show each hint once automatically in the process life.
private final CompatUIHintsState mCompatUIHintsState;
-
private final CompatUIShellCommandHandler mCompatUIShellCommandHandler;
+ private CompatUICallback mCallback;
+
// Indicates if the keyguard is currently showing, in which case compat UIs shouldn't
// be shown.
private boolean mKeyguardShowing;
@@ -372,19 +370,20 @@ public class CompatUIController implements OnDisplaysChangedListener,
RestartDialogWindowManager layout =
mTaskIdToRestartDialogWindowManagerMap.get(taskInfo.taskId);
if (layout != null) {
- // TODO(b/266262111) Handle theme change when taskListener changes
- if (layout.getTaskListener() != taskListener) {
- mSetOfTaskIdsShowingRestartDialog.remove(taskInfo.taskId);
- }
- layout.setRequestRestartDialog(
- mSetOfTaskIdsShowingRestartDialog.contains(taskInfo.taskId));
- // UI already exists, update the UI layout.
- if (!layout.updateCompatInfo(taskInfo, taskListener,
- showOnDisplay(layout.getDisplayId()))) {
- // The layout is no longer eligible to be shown, remove from active layouts.
+ if (layout.needsToBeRecreated(taskInfo, taskListener)) {
mTaskIdToRestartDialogWindowManagerMap.remove(taskInfo.taskId);
+ layout.release();
+ } else {
+ layout.setRequestRestartDialog(
+ mSetOfTaskIdsShowingRestartDialog.contains(taskInfo.taskId));
+ // UI already exists, update the UI layout.
+ if (!layout.updateCompatInfo(taskInfo, taskListener,
+ showOnDisplay(layout.getDisplayId()))) {
+ // The layout is no longer eligible to be shown, remove from active layouts.
+ mTaskIdToRestartDialogWindowManagerMap.remove(taskInfo.taskId);
+ }
+ return;
}
- return;
}
// Create a new UI layout.
final Context context = getOrCreateDisplayContext(taskInfo.displayId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
index db87f657c1b2..cfb2accbcecd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
@@ -151,7 +151,6 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
@Override
public void setConfiguration(Configuration configuration) {
super.setConfiguration(configuration);
- // TODO(b/266262111): Investigate loss of theme configuration when switching TaskListener
mContext = mContext.createConfigurationContext(configuration);
}
@@ -211,7 +210,8 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
}
View layout = getLayout();
- if (layout == null || prevTaskListener != taskListener) {
+ if (layout == null || prevTaskListener != taskListener
+ || mTaskConfig.uiMode != prevTaskConfig.uiMode) {
// Layout wasn't created yet or TaskListener changed, recreate the layout for new
// surface parent.
release();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
index 10f25d0eef11..2440838844c4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
@@ -155,6 +155,11 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract {
return super.updateCompatInfo(taskInfo, taskListener, canShow);
}
+ boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) {
+ return taskInfo.configuration.uiMode != mTaskInfo.configuration.uiMode
+ || !getTaskListener().equals(taskListener);
+ }
+
private void updateDialogMargins() {
if (mLayout == null) {
return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 25c430c27457..ef21c7e9ec0c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -41,6 +41,7 @@ import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.back.BackAnimationController;
import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.bubbles.Bubbles;
+import com.android.wm.shell.common.DevicePostureController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
@@ -50,6 +51,7 @@ import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SystemWindows;
+import com.android.wm.shell.common.TabletopModeController;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ShellAnimationThread;
@@ -160,6 +162,28 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
+ static DevicePostureController provideDevicePostureController(
+ Context context,
+ ShellInit shellInit,
+ @ShellMainThread ShellExecutor mainExecutor
+ ) {
+ return new DevicePostureController(context, shellInit, mainExecutor);
+ }
+
+ @WMSingleton
+ @Provides
+ static TabletopModeController provideTabletopModeController(
+ Context context,
+ ShellInit shellInit,
+ DevicePostureController postureController,
+ DisplayController displayController,
+ @ShellMainThread ShellExecutor mainExecutor) {
+ return new TabletopModeController(
+ context, shellInit, postureController, displayController, mainExecutor);
+ }
+
+ @WMSingleton
+ @Provides
static DragAndDropController provideDragAndDropController(Context context,
ShellInit shellInit,
ShellController shellController,
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 efc7d1ff0bb9..45785238fe00 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
@@ -194,7 +194,8 @@ public abstract class WMShellModule {
DisplayController displayController,
SyncTransactionQueue syncQueue,
Optional<DesktopModeController> desktopModeController,
- Optional<DesktopTasksController> desktopTasksController) {
+ Optional<DesktopTasksController> desktopTasksController,
+ Optional<SplitScreenController> splitScreenController) {
if (DesktopModeStatus.isAnyEnabled()) {
return new DesktopModeWindowDecorViewModel(
context,
@@ -204,7 +205,8 @@ public abstract class WMShellModule {
displayController,
syncQueue,
desktopModeController,
- desktopTasksController);
+ desktopTasksController,
+ splitScreenController);
}
return new CaptionWindowDecorViewModel(
context,
@@ -558,16 +560,18 @@ public abstract class WMShellModule {
static FullscreenUnfoldTaskAnimator provideFullscreenUnfoldTaskAnimator(
Context context,
UnfoldBackgroundController unfoldBackgroundController,
+ ShellController shellController,
DisplayInsetsController displayInsetsController
) {
return new FullscreenUnfoldTaskAnimator(context, unfoldBackgroundController,
- displayInsetsController);
+ shellController, displayInsetsController);
}
@Provides
static SplitTaskUnfoldAnimator provideSplitTaskUnfoldAnimatorBase(
Context context,
UnfoldBackgroundController backgroundController,
+ ShellController shellController,
@ShellMainThread ShellExecutor executor,
Lazy<Optional<SplitScreenController>> splitScreenOptional,
DisplayInsetsController displayInsetsController
@@ -577,7 +581,7 @@ public abstract class WMShellModule {
// controller directly once we refactor ShellTaskOrganizer to not depend on the unfold
// animation controller directly.
return new SplitTaskUnfoldAnimator(context, executor, splitScreenOptional,
- backgroundController, displayInsetsController);
+ shellController, backgroundController, displayInsetsController);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index fce013837f01..73a740381090 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -85,7 +85,7 @@ class DesktopTasksController(
fun showDesktopApps() {
ProtoLog.v(WM_SHELL_DESKTOP_MODE, "showDesktopApps")
val wct = WindowContainerTransaction()
- bringDesktopAppsToFront(wct, force = true)
+ bringDesktopAppsToFront(wct)
// Execute transaction if there are pending operations
if (!wct.isEmpty) {
@@ -156,19 +156,9 @@ class DesktopTasksController(
?: WINDOWING_MODE_UNDEFINED
}
- private fun bringDesktopAppsToFront(wct: WindowContainerTransaction, force: Boolean = false) {
- val activeTasks = desktopModeTaskRepository.getActiveTasks()
-
- // Skip if all tasks are already visible
- if (!force && activeTasks.all(desktopModeTaskRepository::isVisibleTask)) {
- ProtoLog.d(
- WM_SHELL_DESKTOP_MODE,
- "bringDesktopAppsToFront: active tasks are already in front, skipping."
- )
- return
- }
-
+ private fun bringDesktopAppsToFront(wct: WindowContainerTransaction) {
ProtoLog.v(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront")
+ val activeTasks = desktopModeTaskRepository.getActiveTasks()
// First move home to front and then other tasks on top of it
moveHomeTaskToFront(wct)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java
new file mode 100644
index 000000000000..20da54efd286
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java
@@ -0,0 +1,27 @@
+/*
+ * 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.wm.shell.draganddrop;
+
+/** Constants that can be used by both Shell and other users of the library, e.g. Launcher */
+public class DragAndDropConstants {
+
+ /**
+ * An Intent extra that Launcher can use to specify a region of the screen where Shell should
+ * ignore drag events.
+ */
+ public static final String EXTRA_DISALLOW_HIT_REGION = "DISALLOW_HIT_REGION";
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index b59fe1818780..4cfaae6e51c7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -36,6 +36,7 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_U
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import android.content.ClipDescription;
+import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
@@ -58,9 +59,9 @@ import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.annotations.ExternalMainThread;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.sysui.ConfigurationChangeListener;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -70,7 +71,7 @@ import java.util.ArrayList;
* Handles the global drag and drop handling for the Shell.
*/
public class DragAndDropController implements DisplayController.OnDisplaysChangedListener,
- View.OnDragListener, ConfigurationChangeListener {
+ View.OnDragListener, ComponentCallbacks2 {
private static final String TAG = DragAndDropController.class.getSimpleName();
@@ -119,7 +120,6 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
mMainExecutor.executeDelayed(() -> {
mDisplayController.addDisplayWindowListener(this);
}, 0);
- mShellController.addConfigurationChangeListener(this);
}
/**
@@ -180,6 +180,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
try {
wm.addView(rootView, layoutParams);
addDisplayDropTarget(displayId, context, wm, rootView, dragLayout);
+ context.registerComponentCallbacks(this);
} catch (WindowManager.InvalidDisplayException e) {
Slog.w(TAG, "Unable to add view for display id: " + displayId);
}
@@ -209,6 +210,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
if (pd == null) {
return;
}
+ pd.context.unregisterComponentCallbacks(this);
pd.wm.removeViewImmediate(pd.rootView);
mDisplayDropTargets.remove(displayId);
}
@@ -328,18 +330,29 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
return mimeTypes;
}
+ // Note: Component callbacks are always called on the main thread of the process
+ @ExternalMainThread
@Override
- public void onThemeChanged() {
- for (int i = 0; i < mDisplayDropTargets.size(); i++) {
- mDisplayDropTargets.get(i).dragLayout.onThemeChange();
- }
+ public void onConfigurationChanged(Configuration newConfig) {
+ mMainExecutor.execute(() -> {
+ for (int i = 0; i < mDisplayDropTargets.size(); i++) {
+ mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig);
+ }
+ });
}
+ // Note: Component callbacks are always called on the main thread of the process
+ @ExternalMainThread
@Override
- public void onConfigurationChanged(Configuration newConfig) {
- for (int i = 0; i < mDisplayDropTargets.size(); i++) {
- mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig);
- }
+ public void onTrimMemory(int level) {
+ // Do nothing
+ }
+
+ // Note: Component callbacks are always called on the main thread of the process
+ @ExternalMainThread
+ @Override
+ public void onLowMemory() {
+ // Do nothing
}
private static class PerDisplay {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index d93a9012c8f1..df94b414c092 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -34,6 +34,7 @@ import static android.content.Intent.EXTRA_USER;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
+import static com.android.wm.shell.draganddrop.DragAndDropConstants.EXTRA_DISALLOW_HIT_REGION;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_FULLSCREEN;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT;
@@ -53,6 +54,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.LauncherApps;
import android.graphics.Insets;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -86,6 +88,7 @@ public class DragAndDropPolicy {
private final Starter mStarter;
private final SplitScreenController mSplitScreen;
private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>();
+ private final RectF mDisallowHitRegion = new RectF();
private InstanceId mLoggerSessionId;
private DragSession mSession;
@@ -111,6 +114,12 @@ public class DragAndDropPolicy {
mSession = new DragSession(mActivityTaskManager, displayLayout, data);
// TODO(b/169894807): Also update the session data with task stack changes
mSession.update();
+ RectF disallowHitRegion = (RectF) mSession.dragData.getExtra(EXTRA_DISALLOW_HIT_REGION);
+ if (disallowHitRegion == null) {
+ mDisallowHitRegion.setEmpty();
+ } else {
+ mDisallowHitRegion.set(disallowHitRegion);
+ }
}
/**
@@ -218,6 +227,9 @@ public class DragAndDropPolicy {
*/
@Nullable
Target getTargetAtLocation(int x, int y) {
+ if (mDisallowHitRegion.contains(x, y)) {
+ return null;
+ }
for (int i = mTargets.size() - 1; i >= 0; i--) {
DragAndDropPolicy.Target t = mTargets.get(i);
if (t.hitRegion.contains(x, y)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index 3ade1ed9392f..fe42822ab6a1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -18,6 +18,8 @@ package com.android.wm.shell.draganddrop;
import static android.app.StatusBarManager.DISABLE_NONE;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.content.pm.ActivityInfo.CONFIG_ASSETS_PATHS;
+import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -72,6 +74,7 @@ public class DragLayout extends LinearLayout {
private final SplitScreenController mSplitScreenController;
private final IconProvider mIconProvider;
private final StatusBarManager mStatusBarManager;
+ private final Configuration mLastConfiguration = new Configuration();
private DragAndDropPolicy.Target mCurrentTarget = null;
private DropZoneView mDropZoneView1;
@@ -92,6 +95,7 @@ public class DragLayout extends LinearLayout {
mIconProvider = iconProvider;
mPolicy = new DragAndDropPolicy(context, splitScreenController);
mStatusBarManager = context.getSystemService(StatusBarManager.class);
+ mLastConfiguration.setTo(context.getResources().getConfiguration());
mDisplayMargin = context.getResources().getDimensionPixelSize(
R.dimen.drop_layout_display_margin);
@@ -118,7 +122,7 @@ public class DragLayout extends LinearLayout {
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mInsets = insets.getInsets(Type.systemBars() | Type.displayCutout());
+ mInsets = insets.getInsets(Type.tappableElement() | Type.displayCutout());
recomputeDropTargets();
final int orientation = getResources().getConfiguration().orientation;
@@ -132,11 +136,6 @@ public class DragLayout extends LinearLayout {
return super.onApplyWindowInsets(insets);
}
- public void onThemeChange() {
- mDropZoneView1.onThemeChange();
- mDropZoneView2.onThemeChange();
- }
-
public void onConfigChanged(Configuration newConfig) {
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE
&& getOrientation() != HORIZONTAL) {
@@ -147,6 +146,15 @@ public class DragLayout extends LinearLayout {
setOrientation(LinearLayout.VERTICAL);
updateContainerMargins(newConfig.orientation);
}
+
+ final int diff = newConfig.diff(mLastConfiguration);
+ final boolean themeChanged = (diff & CONFIG_ASSETS_PATHS) != 0
+ || (diff & CONFIG_UI_MODE) != 0;
+ if (themeChanged) {
+ mDropZoneView1.onThemeChange();
+ mDropZoneView2.onThemeChange();
+ }
+ mLastConfiguration.setTo(newConfig);
}
private void updateContainerMarginsForSingleTask() {
@@ -369,7 +377,9 @@ public class DragLayout extends LinearLayout {
// Start animating the drop UI out with the drag surface
hide(event, dropCompleteCallback);
- hideDragSurface(dragSurface);
+ if (handledDrop) {
+ hideDragSurface(dragSurface);
+ }
return handledDrop;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
index 26f47fcdaa44..d094c229e0f8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
@@ -108,6 +108,10 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
}
if (!createdWindowDecor) {
mSyncQueue.runInSync(t -> {
+ if (!leash.isValid()) {
+ // Task vanished before sync completion
+ return;
+ }
// Reset several properties back to fullscreen (PiP, for example, leaves all these
// properties in a bad state).
t.setWindowCrop(leash, null);
@@ -136,6 +140,10 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
final Point positionInParent = state.mTaskInfo.positionInParent;
if (!oldPositionInParent.equals(state.mTaskInfo.positionInParent)) {
mSyncQueue.runInSync(t -> {
+ if (!state.mLeash.isValid()) {
+ // Task vanished before sync completion
+ return;
+ }
t.setPosition(state.mLeash, positionInParent.x, positionInParent.y);
});
}
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
index ac13f96585b6..f9e0ca53b32d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
@@ -247,6 +247,11 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
mLaunchRootTask = taskInfo;
}
+ if (mHomeTask != null && mHomeTask.taskId == taskInfo.taskId
+ && !taskInfo.equals(mHomeTask)) {
+ mHomeTask = taskInfo;
+ }
+
super.onTaskInfoChanged(taskInfo);
}
@@ -364,6 +369,7 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
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 -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
index 2624ee536b58..d961d8658b98 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
@@ -70,4 +70,9 @@ interface IPip {
* Sets the next pip animation type to be the alpha animation.
*/
oneway void setPipAnimationTypeToAlpha() = 5;
+
+ /**
+ * Sets the height and visibility of the Launcher keep clear area.
+ */
+ oneway void setLauncherKeepClearAreaHeight(boolean visible, int height) = 6;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index d9ac76e833d8..fe8ede67c415 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -36,6 +36,7 @@ import android.window.TaskSnapshot;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
+import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.transition.Transitions;
@@ -209,7 +210,7 @@ public class PipAnimationController {
/**
* Quietly cancel the animator by removing the listeners first.
*/
- static void quietCancel(@NonNull ValueAnimator animator) {
+ public static void quietCancel(@NonNull ValueAnimator animator) {
animator.removeAllUpdateListeners();
animator.removeAllListeners();
animator.cancel();
@@ -372,7 +373,8 @@ public class PipAnimationController {
void setAppIconContentOverlay(Context context, Rect bounds, ActivityInfo activityInfo) {
reattachContentOverlay(
- new PipContentOverlay.PipAppIconOverlay(context, bounds, activityInfo));
+ new PipContentOverlay.PipAppIconOverlay(context, bounds,
+ () -> new IconProvider(context).getIcon(activityInfo)));
}
private void reattachContentOverlay(PipContentOverlay overlay) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java
index 480bf93b2ddb..d228dfbb7705 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java
@@ -20,9 +20,6 @@ import static android.util.TypedValue.COMPLEX_UNIT_DIP;
import android.annotation.Nullable;
import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -35,10 +32,15 @@ import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.window.TaskSnapshot;
+import java.util.function.Supplier;
+
/**
* Represents the content overlay used during the entering PiP animation.
*/
public abstract class PipContentOverlay {
+ // Fixed string used in WMShellFlickerTests
+ protected static final String LAYER_NAME = "PipContentOverlay";
+
protected SurfaceControl mLeash;
/** Attaches the internal {@link #mLeash} to the given parent leash. */
@@ -86,7 +88,7 @@ public abstract class PipContentOverlay {
mContext = context;
mLeash = new SurfaceControl.Builder(new SurfaceSession())
.setCallsite(TAG)
- .setName(TAG)
+ .setName(LAYER_NAME)
.setColorLayer()
.build();
}
@@ -139,7 +141,7 @@ public abstract class PipContentOverlay {
mSourceRectHint = new Rect(sourceRectHint);
mLeash = new SurfaceControl.Builder(new SurfaceSession())
.setCallsite(TAG)
- .setName(TAG)
+ .setName(LAYER_NAME)
.build();
}
@@ -174,7 +176,9 @@ public abstract class PipContentOverlay {
/** A {@link PipContentOverlay} shows app icon on solid color background. */
public static final class PipAppIconOverlay extends PipContentOverlay {
private static final String TAG = PipAppIconOverlay.class.getSimpleName();
- private static final int APP_ICON_SIZE_DP = 48;
+ // Align with the practical / reasonable launcher:iconImageSize as in
+ // vendor/unbundled_google/packages/NexusLauncher/res/xml/device_profiles.xml
+ private static final int APP_ICON_SIZE_DP = 66;
private final Context mContext;
private final int mAppIconSizePx;
@@ -184,17 +188,17 @@ public abstract class PipContentOverlay {
private Bitmap mBitmap;
- public PipAppIconOverlay(Context context, Rect appBounds, ActivityInfo activityInfo) {
+ public PipAppIconOverlay(Context context, Rect appBounds, Supplier<Drawable> iconSupplier) {
mContext = context;
mAppIconSizePx = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, APP_ICON_SIZE_DP,
context.getResources().getDisplayMetrics());
mAppBounds = new Rect(appBounds);
mBitmap = Bitmap.createBitmap(appBounds.width(), appBounds.height(),
Bitmap.Config.ARGB_8888);
- prepareAppIconOverlay(activityInfo);
+ prepareAppIconOverlay(iconSupplier);
mLeash = new SurfaceControl.Builder(new SurfaceSession())
.setCallsite(TAG)
- .setName(TAG)
+ .setName(LAYER_NAME)
.build();
}
@@ -234,7 +238,7 @@ public abstract class PipContentOverlay {
}
}
- private void prepareAppIconOverlay(ActivityInfo activityInfo) {
+ private void prepareAppIconOverlay(Supplier<Drawable> iconSupplier) {
final Canvas canvas = new Canvas();
canvas.setBitmap(mBitmap);
final TypedArray ta = mContext.obtainStyledAttributes(new int[] {
@@ -248,8 +252,7 @@ public abstract class PipContentOverlay {
} finally {
ta.recycle();
}
- final Drawable appIcon = loadActivityInfoIcon(activityInfo,
- mContext.getResources().getConfiguration().densityDpi);
+ final Drawable appIcon = iconSupplier.get();
final Rect appIconBounds = new Rect(
mAppBounds.centerX() - mAppIconSizePx / 2,
mAppBounds.centerY() - mAppIconSizePx / 2,
@@ -259,24 +262,5 @@ public abstract class PipContentOverlay {
appIcon.draw(canvas);
mBitmap = mBitmap.copy(Bitmap.Config.HARDWARE, false /* mutable */);
}
-
- // Copied from com.android.launcher3.icons.IconProvider#loadActivityInfoIcon
- private Drawable loadActivityInfoIcon(ActivityInfo ai, int density) {
- final int iconRes = ai.getIconResource();
- Drawable icon = null;
- // Get the preferred density icon from the app's resources
- if (density != 0 && iconRes != 0) {
- try {
- final Resources resources = mContext.getPackageManager()
- .getResourcesForApplication(ai.applicationInfo);
- icon = resources.getDrawableForDensity(iconRes, density);
- } catch (PackageManager.NameNotFoundException | Resources.NotFoundException exc) { }
- }
- // Get the default density icon
- if (icon == null) {
- icon = ai.loadIcon(mContext.getPackageManager());
- }
- return icon;
- }
}
}
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 f11836ea5bee..eb336d56b62c 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
@@ -1179,6 +1179,20 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
}
/**
+ * Directly update the animator bounds.
+ */
+ public void updateAnimatorBounds(Rect bounds) {
+ final PipAnimationController.PipTransitionAnimator animator =
+ mPipAnimationController.getCurrentAnimator();
+ if (animator != null && animator.isRunning()) {
+ if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
+ animator.updateEndValue(bounds);
+ }
+ animator.setDestinationBounds(bounds);
+ }
+ }
+
+ /**
* Handles all changes to the PictureInPictureParams.
*/
protected void applyNewPictureInPictureParams(@NonNull PictureInPictureParams params) {
@@ -1594,7 +1608,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
// source rect hint to enter PiP use bounds animation.
if (sourceHintRect == null) {
if (SystemProperties.getBoolean(
- "persist.wm.debug.enable_pip_app_icon_overlay", false)) {
+ "persist.wm.debug.enable_pip_app_icon_overlay", true)) {
animator.setAppIconContentOverlay(
mContext, currentBounds, mTaskInfo.topActivityInfo);
} else {
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 e5c0570841f4..e01b406eb4c1 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
@@ -803,8 +803,15 @@ public class PipTransition extends PipTransitionController {
if (sourceHintRect == null) {
// We use content overlay when there is no source rect hint to enter PiP use bounds
// animation.
+ // TODO(b/272819817): cleanup the null-check and extra logging.
+ final boolean hasTopActivityInfo = taskInfo.topActivityInfo != null;
+ if (!hasTopActivityInfo) {
+ ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ "%s: TaskInfo.topActivityInfo is null", TAG);
+ }
if (SystemProperties.getBoolean(
- "persist.wm.debug.enable_pip_app_icon_overlay", false)) {
+ "persist.wm.debug.enable_pip_app_icon_overlay", true)
+ && hasTopActivityInfo) {
animator.setAppIconContentOverlay(
mContext, currentBounds, taskInfo.topActivityInfo);
} else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
index c6b5ce93fd35..db6138a0891f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
@@ -93,6 +93,11 @@ public class PipTransitionState {
return hasEnteredPip(mState);
}
+ /** Returns true if activity is currently entering PiP mode. */
+ public boolean isEnteringPip() {
+ return isEnteringPip(mState);
+ }
+
public void setInSwipePipToHomeTransition(boolean inSwipePipToHomeTransition) {
mInSwipePipToHomeTransition = inSwipePipToHomeTransition;
}
@@ -130,6 +135,11 @@ public class PipTransitionState {
return state == ENTERED_PIP;
}
+ /** Returns true if activity is currently entering PiP mode. */
+ public static boolean isEnteringPip(@TransitionState int state) {
+ return state == ENTERING_PIP;
+ }
+
public interface OnPipTransitionStateChangedListener {
void onPipTransitionStateChanged(@TransitionState int oldState,
@TransitionState int newState);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index ec34f73126fb..0d5f1432d204 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -101,6 +101,7 @@ import com.android.wm.shell.sysui.UserChangeListener;
import com.android.wm.shell.transition.Transitions;
import java.io.PrintWriter;
+import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -181,14 +182,20 @@ public class PipController implements PipTransitionController.PipTransitionCallb
// early bail out if the keep clear areas feature is disabled
return;
}
- // only move if already in pip, other transitions account for keep clear areas
- if (mPipTransitionState.hasEnteredPip()) {
+ // only move if we're in PiP or transitioning into PiP
+ if (!mPipTransitionState.shouldBlockResizeRequest()) {
Rect destBounds = mPipKeepClearAlgorithm.adjust(mPipBoundsState,
mPipBoundsAlgorithm);
// only move if the bounds are actually different
if (destBounds != mPipBoundsState.getBounds()) {
- mPipTaskOrganizer.scheduleAnimateResizePip(destBounds,
- mEnterAnimationDuration, null);
+ if (mPipTransitionState.hasEnteredPip()) {
+ // if already in PiP, schedule separate animation
+ mPipTaskOrganizer.scheduleAnimateResizePip(destBounds,
+ mEnterAnimationDuration, null);
+ } else if (mPipTransitionState.isEnteringPip()) {
+ // while entering PiP we just need to update animator bounds
+ mPipTaskOrganizer.updateAnimatorBounds(destBounds);
+ }
}
}
}
@@ -715,6 +722,12 @@ public class PipController implements PipTransitionController.PipTransitionCallb
private void onDisplayChanged(DisplayLayout layout, boolean saveRestoreSnapFraction) {
if (!mPipBoundsState.getDisplayLayout().isSameGeometry(layout)) {
+ PipAnimationController.PipTransitionAnimator animator =
+ mPipAnimationController.getCurrentAnimator();
+ if (animator != null && animator.isRunning()) {
+ // cancel any running animator, as it is using stale display layout information
+ PipAnimationController.quietCancel(animator);
+ }
onDisplayChangedUncheck(layout, saveRestoreSnapFraction);
}
}
@@ -868,6 +881,21 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
}
+ private void setLauncherKeepClearAreaHeight(boolean visible, int height) {
+ if (visible) {
+ Rect rect = new Rect(
+ 0, mPipBoundsState.getDisplayBounds().bottom - height,
+ mPipBoundsState.getDisplayBounds().right,
+ mPipBoundsState.getDisplayBounds().bottom);
+ Set<Rect> restrictedKeepClearAreas = new HashSet<>(
+ mPipBoundsState.getRestrictedKeepClearAreas());
+ restrictedKeepClearAreas.add(rect);
+ mPipBoundsState.setKeepClearAreas(restrictedKeepClearAreas,
+ mPipBoundsState.getUnrestrictedKeepClearAreas());
+ updatePipPositionForKeepClearAreas();
+ }
+ }
+
private void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) {
mOnIsInPipStateChangedListener = callback;
if (mOnIsInPipStateChangedListener != null) {
@@ -1231,6 +1259,14 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
@Override
+ public void setLauncherKeepClearAreaHeight(boolean visible, int height) {
+ executeRemoteCallWithTaskPermission(mController, "setLauncherKeepClearAreaHeight",
+ (controller) -> {
+ controller.setLauncherKeepClearAreaHeight(visible, height);
+ });
+ }
+
+ @Override
public void setPipAnimationListener(IPipAnimationListener listener) {
executeRemoteCallWithTaskPermission(mController, "setPipAnimationListener",
(controller) -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
index 7619646804ad..9729a4007bac 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
@@ -235,21 +235,14 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
/** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
public void createOrUpdateDismissTarget() {
- if (!mTargetViewContainer.isAttachedToWindow()) {
+ if (mTargetViewContainer.getParent() == null) {
mTargetViewContainer.cancelAnimators();
mTargetViewContainer.setVisibility(View.INVISIBLE);
mTargetViewContainer.getViewTreeObserver().removeOnPreDrawListener(this);
mHasDismissTargetSurface = false;
- try {
- mWindowManager.addView(mTargetViewContainer, getDismissTargetLayoutParams());
- } catch (IllegalStateException e) {
- // This shouldn't happen, but if the target is already added, just update its layout
- // params.
- mWindowManager.updateViewLayout(
- mTargetViewContainer, getDismissTargetLayoutParams());
- }
+ mWindowManager.addView(mTargetViewContainer, getDismissTargetLayoutParams());
} else {
mWindowManager.updateViewLayout(mTargetViewContainer, getDismissTargetLayoutParams());
}
@@ -306,7 +299,7 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
* Removes the dismiss target and cancels any pending callbacks to show it.
*/
public void cleanUpDismissTarget() {
- if (mTargetViewContainer.isAttachedToWindow()) {
+ if (mTargetViewContainer.getParent() != null) {
mWindowManager.removeViewImmediate(mTargetViewContainer);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
index 75f9a4c33af9..c9b3a1af6507 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
@@ -50,6 +50,8 @@ public enum ShellProtoLogGroup implements IProtoLogGroup {
Consts.TAG_WM_SHELL),
WM_SHELL_FLOATING_APPS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
Consts.TAG_WM_SHELL),
+ WM_SHELL_FOLDABLE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
+ Consts.TAG_WM_SHELL),
TEST_GROUP(true, true, false, "WindowManagerShellProtoLogTest");
private final boolean mEnabled;
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 c7ad4fdcacf0..94b9e907fa76 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
@@ -422,6 +422,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
mStageCoordinator.goToFullscreenFromSplit();
}
+ /** Move the specified task to fullscreen, regardless of focus state. */
+ public void moveTaskToFullscreen(int taskId) {
+ mStageCoordinator.moveTaskToFullscreen(taskId);
+ }
+
public boolean isLaunchToSplit(TaskInfo taskInfo) {
return mStageCoordinator.isLaunchToSplit(taskInfo);
}
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 2a6fbd2cee8c..71ee690146f9 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
@@ -204,9 +204,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// and exit, since exit itself can trigger a number of changes that update the stages.
private boolean mShouldUpdateRecents;
private boolean mExitSplitScreenOnHide;
- private boolean mIsSplitEntering;
+ private boolean mIsDividerRemoteAnimating;
private boolean mIsDropEntering;
private boolean mIsExiting;
+ private boolean mIsRootTranslucent;
private DefaultMixedHandler mMixedHandler;
private final Toast mSplitUnsupportedToast;
@@ -422,6 +423,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
}
+ if (!isSplitActive()) {
+ // prevent the fling divider to center transitioni if split screen didn't active.
+ mIsDropEntering = true;
+ }
+
setSideStagePosition(sideStagePosition, wct);
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
targetStage.evictAllChildren(evictWct);
@@ -436,28 +442,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// reparent the task to an invisible split root will make the activity invisible. Reorder
// the root task to front to make the entering transition from pip to split smooth.
wct.reorder(mRootTaskInfo.token, true);
- wct.setForceTranslucent(mRootTaskInfo.token, true);
wct.reorder(targetStage.mRootTaskInfo.token, true);
- wct.setForceTranslucent(targetStage.mRootTaskInfo.token, true);
- // prevent the fling divider to center transition
- mIsDropEntering = true;
-
targetStage.addTask(task, wct);
- if (ENABLE_SHELL_TRANSITIONS) {
- prepareEnterSplitScreen(wct);
- mSplitTransitions.startEnterTransition(TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE, wct,
- null, this, null /* consumedCallback */, (finishWct, finishT) -> {
- if (!evictWct.isEmpty()) {
- finishWct.merge(evictWct, true);
- }
- } /* finishedCallback */);
- } else {
- if (!evictWct.isEmpty()) {
- wct.merge(evictWct, true /* transfer */);
- }
- mTaskOrganizer.applyTransaction(wct);
+ if (!evictWct.isEmpty()) {
+ wct.merge(evictWct, true /* transfer */);
}
+ mTaskOrganizer.applyTransaction(wct);
return true;
}
@@ -716,7 +707,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSplitLayout.setDivideRatio(splitRatio);
updateWindowBounds(mSplitLayout, wct);
wct.reorder(mRootTaskInfo.token, true);
- wct.setForceTranslucent(mRootTaskInfo.token, false);
+ setRootForceTranslucent(false, wct);
// Make sure the launch options will put tasks in the corresponding split roots
mainOptions = mainOptions != null ? mainOptions : new Bundle();
@@ -764,17 +755,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
if (pendingIntent2 == null) {
- // Launching a solo task.
- ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
- activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
- options1 = activityOptions.toBundle();
- addActivityOptions(options1, null /* launchTarget */);
- if (shortcutInfo1 != null) {
- wct.startShortcut(mContext.getPackageName(), shortcutInfo1, options1);
- } else {
- wct.sendPendingIntent(pendingIntent1, fillInIntent1, options1);
- }
- mSyncQueue.queue(wct);
+ // Launching a solo intent or shortcut as fullscreen.
+ launchAsFullscreenWithRemoteAnimation(pendingIntent1, fillInIntent1, shortcutInfo1,
+ options1, adapter, wct);
return;
}
@@ -797,13 +780,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
if (taskId == INVALID_TASK_ID) {
- // Launching a solo task.
- ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
- activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
- options1 = activityOptions.toBundle();
- addActivityOptions(options1, null /* launchTarget */);
- wct.sendPendingIntent(pendingIntent, fillInIntent, options1);
- mSyncQueue.queue(wct);
+ // Launching a solo intent as fullscreen.
+ launchAsFullscreenWithRemoteAnimation(pendingIntent, fillInIntent, null, options1,
+ adapter, wct);
return;
}
@@ -822,13 +801,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
if (taskId == INVALID_TASK_ID) {
- // Launching a solo task.
- ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
- activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
- options1 = activityOptions.toBundle();
- addActivityOptions(options1, null /* launchTarget */);
- wct.startShortcut(mContext.getPackageName(), shortcutInfo, options1);
- mSyncQueue.queue(wct);
+ // Launching a solo shortcut as fullscreen.
+ launchAsFullscreenWithRemoteAnimation(null, null, shortcutInfo, options1, adapter, wct);
return;
}
@@ -838,6 +812,49 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
instanceId);
}
+ private void launchAsFullscreenWithRemoteAnimation(@Nullable PendingIntent pendingIntent,
+ @Nullable Intent fillInIntent, @Nullable ShortcutInfo shortcutInfo,
+ @Nullable Bundle options, RemoteAnimationAdapter adapter,
+ WindowContainerTransaction wct) {
+ LegacyTransitions.ILegacyTransition transition =
+ (transit, apps, wallpapers, nonApps, finishedCallback, t) -> {
+ if (apps == null || apps.length == 0) {
+ onRemoteAnimationFinished(apps);
+ t.apply();
+ try {
+ adapter.getRunner().onAnimationCancelled(mKeyguardShowing);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error starting remote animation", e);
+ }
+ return;
+ }
+
+ for (int i = 0; i < apps.length; ++i) {
+ if (apps[i].mode == MODE_OPENING) {
+ t.show(apps[i].leash);
+ }
+ }
+ t.apply();
+
+ try {
+ adapter.getRunner().onAnimationStart(
+ transit, apps, wallpapers, nonApps, finishedCallback);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error starting remote animation", e);
+ }
+ };
+
+ addActivityOptions(options, null /* launchTarget */);
+ if (shortcutInfo != null) {
+ wct.startShortcut(mContext.getPackageName(), shortcutInfo, options);
+ } else if (pendingIntent != null) {
+ wct.sendPendingIntent(pendingIntent, fillInIntent, options);
+ } else {
+ Slog.e(TAG, "Pending intent and shortcut are null is invalid case.");
+ }
+ mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
+ }
+
private void startWithLegacyTransition(WindowContainerTransaction wct,
@Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
@Nullable ShortcutInfo mainShortcutInfo, @Nullable Bundle mainOptions,
@@ -881,7 +898,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Set false to avoid record new bounds with old task still on top;
mShouldUpdateRecents = false;
- mIsSplitEntering = true;
+ mIsDividerRemoteAnimating = true;
if (mSplitRequest == null) {
mSplitRequest = new SplitRequest(mainTaskId,
mainPendingIntent != null ? mainPendingIntent.getIntent() : null,
@@ -894,23 +911,25 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (options == null) options = new Bundle();
addActivityOptions(options, mMainStage);
- options = wrapAsSplitRemoteAnimation(adapter, options);
updateWindowBounds(mSplitLayout, wct);
+ wct.reorder(mRootTaskInfo.token, true);
+ setRootForceTranslucent(false, wct);
// TODO(b/268008375): Merge APIs to start a split pair into one.
if (mainTaskId != INVALID_TASK_ID) {
+ options = wrapAsSplitRemoteAnimation(adapter, options);
wct.startTask(mainTaskId, options);
- } else if (mainShortcutInfo != null) {
- wct.startShortcut(mContext.getPackageName(), mainShortcutInfo, options);
+ mSyncQueue.queue(wct);
} else {
- wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, options);
+ if (mainShortcutInfo != null) {
+ wct.startShortcut(mContext.getPackageName(), mainShortcutInfo, options);
+ } else {
+ wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, options);
+ }
+ mSyncQueue.queue(wrapAsSplitRemoteAnimation(adapter), WindowManager.TRANSIT_OPEN, wct);
}
- wct.reorder(mRootTaskInfo.token, true);
- wct.setForceTranslucent(mRootTaskInfo.token, false);
-
- mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
setDividerVisibility(true, t);
});
@@ -936,7 +955,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
new IRemoteAnimationFinishedCallback.Stub() {
@Override
public void onAnimationFinished() throws RemoteException {
- onRemoteAnimationFinishedOrCancelled(false /* cancel */, evictWct);
+ onRemoteAnimationFinishedOrCancelled(evictWct);
finishedCallback.onAnimationFinished();
}
};
@@ -952,7 +971,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onAnimationCancelled(boolean isKeyguardOccluded) {
- onRemoteAnimationFinishedOrCancelled(true /* cancel */, evictWct);
+ onRemoteAnimationFinishedOrCancelled(evictWct);
try {
adapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
} catch (RemoteException e) {
@@ -967,21 +986,68 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return activityOptions.toBundle();
}
+ private LegacyTransitions.ILegacyTransition wrapAsSplitRemoteAnimation(
+ RemoteAnimationAdapter adapter) {
+ LegacyTransitions.ILegacyTransition transition =
+ (transit, apps, wallpapers, nonApps, finishedCallback, t) -> {
+ if (apps == null || apps.length == 0) {
+ onRemoteAnimationFinished(apps);
+ t.apply();
+ try {
+ adapter.getRunner().onAnimationCancelled(mKeyguardShowing);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error starting remote animation", e);
+ }
+ return;
+ }
+
+ // Wrap the divider bar into non-apps target to animate together.
+ nonApps = ArrayUtils.appendElement(RemoteAnimationTarget.class, nonApps,
+ getDividerBarLegacyTarget());
+
+ for (int i = 0; i < apps.length; ++i) {
+ if (apps[i].mode == MODE_OPENING) {
+ t.show(apps[i].leash);
+ // Reset the surface position of the opening app to prevent offset.
+ t.setPosition(apps[i].leash, 0, 0);
+ }
+ }
+ t.apply();
+
+ IRemoteAnimationFinishedCallback wrapCallback =
+ new IRemoteAnimationFinishedCallback.Stub() {
+ @Override
+ public void onAnimationFinished() throws RemoteException {
+ onRemoteAnimationFinished(apps);
+ finishedCallback.onAnimationFinished();
+ }
+ };
+ Transitions.setRunningRemoteTransitionDelegate(adapter.getCallingApplication());
+ try {
+ adapter.getRunner().onAnimationStart(
+ transit, apps, wallpapers, nonApps, wrapCallback);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error starting remote animation", e);
+ }
+ };
+
+ return transition;
+ }
+
private void setEnterInstanceId(InstanceId instanceId) {
if (instanceId != null) {
mLogger.enterRequested(instanceId, ENTER_REASON_LAUNCHER);
}
}
- private void onRemoteAnimationFinishedOrCancelled(boolean cancel,
- WindowContainerTransaction evictWct) {
- mIsSplitEntering = false;
+ private void onRemoteAnimationFinishedOrCancelled(WindowContainerTransaction evictWct) {
+ mIsDividerRemoteAnimating = false;
mShouldUpdateRecents = true;
mSplitRequest = null;
// If any stage has no child after animation finished, it means that split will display
// nothing, such status will happen if task and intent is same app but not support
// multi-instance, we should exit split and expand that app as full screen.
- if (!cancel && (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0)) {
+ if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
mMainExecutor.execute(() ->
exitSplitScreen(mMainStage.getChildCount() == 0
? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
@@ -994,6 +1060,27 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
}
+ private void onRemoteAnimationFinished(RemoteAnimationTarget[] apps) {
+ mIsDividerRemoteAnimating = false;
+ mShouldUpdateRecents = true;
+ mSplitRequest = null;
+ // If any stage has no child after finished animation, that side of the split will display
+ // nothing. This might happen if starting the same app on the both sides while not
+ // supporting multi-instance. Exit the split screen and expand that app to full screen.
+ if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
+ mMainExecutor.execute(() -> exitSplitScreen(mMainStage.getChildCount() == 0
+ ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
+ mSplitUnsupportedToast.show();
+ return;
+ }
+
+ final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+ prepareEvictNonOpeningChildTasks(SPLIT_POSITION_TOP_OR_LEFT, apps, evictWct);
+ prepareEvictNonOpeningChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, apps, evictWct);
+ mSyncQueue.queue(evictWct);
+ }
+
+
/**
* Collects all the current child tasks of a specific split and prepares transaction to evict
* them to display.
@@ -1236,19 +1323,19 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// 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(exitReason) && mShouldUpdateRecents) {
- recentTasks.removeSplitPair(mMainStage.getLastVisibleTaskId());
- recentTasks.removeSplitPair(mSideStage.getLastVisibleTaskId());
+ recentTasks.removeSplitPair(mMainStage.getTopVisibleChildTaskId());
+ recentTasks.removeSplitPair(mSideStage.getTopVisibleChildTaskId());
}
});
mShouldUpdateRecents = false;
- mIsSplitEntering = false;
+ mIsDividerRemoteAnimating = false;
mSplitLayout.getInvisibleBounds(mTempRect1);
if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) {
mSideStage.removeAllTasks(wct, false /* toTop */);
mMainStage.deactivate(wct, false /* toTop */);
wct.reorder(mRootTaskInfo.token, false /* onTop */);
- wct.setForceTranslucent(mRootTaskInfo.token, true);
+ setRootForceTranslucent(true, wct);
wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
onTransitionAnimationComplete();
} else {
@@ -1280,7 +1367,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mMainStage.deactivate(finishedWCT, childrenToTop == mMainStage /* toTop */);
mSideStage.removeAllTasks(finishedWCT, childrenToTop == mSideStage /* toTop */);
finishedWCT.reorder(mRootTaskInfo.token, false /* toTop */);
- finishedWCT.setForceTranslucent(mRootTaskInfo.token, true);
+ setRootForceTranslucent(true, wct);
finishedWCT.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
mSyncQueue.queue(finishedWCT);
mSyncQueue.runInSync(at -> {
@@ -1392,7 +1479,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mMainStage.activate(wct, true /* includingTopTask */);
updateWindowBounds(mSplitLayout, wct);
wct.reorder(mRootTaskInfo.token, true);
- wct.setForceTranslucent(mRootTaskInfo.token, false);
+ setRootForceTranslucent(false, wct);
}
void finishEnterSplitScreen(SurfaceControl.Transaction t) {
@@ -1574,7 +1661,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
&& !ENABLE_SHELL_TRANSITIONS) {
// Clear the divider remote animating flag as the divider will be re-rendered to apply
// the new rotation config.
- mIsSplitEntering = false;
+ mIsDividerRemoteAnimating = false;
mSplitLayout.update(null /* t */);
onLayoutSizeChanged(mSplitLayout);
}
@@ -1596,6 +1683,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mRootTaskInfo = null;
mRootTaskLeash = null;
+ mIsRootTranslucent = false;
}
@@ -1614,7 +1702,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Make the stages adjacent to each other so they occlude what's behind them.
wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token);
wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
- wct.setForceTranslucent(mRootTaskInfo.token, true);
+ setRootForceTranslucent(true, wct);
mSplitLayout.getInvisibleBounds(mTempRect1);
wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
mSyncQueue.queue(wct);
@@ -1624,9 +1712,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
void onChildTaskAppeared(StageListenerImpl stageListener, int taskId) {
+ // Handle entering split screen while there is a split pair running in the background.
if (stageListener == mSideStageListener && !isSplitScreenVisible() && isSplitActive()
- && !mIsSplitEntering) {
- // Handle entring split case here if split already running background.
+ && mSplitRequest == null) {
if (mIsDropEntering) {
mSplitLayout.resetDividerPosition();
} else {
@@ -1638,7 +1726,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSideStage.evictOtherChildren(wct, taskId);
updateWindowBounds(mSplitLayout, wct);
wct.reorder(mRootTaskInfo.token, true);
- wct.setForceTranslucent(mRootTaskInfo.token, false);
+ setRootForceTranslucent(false, wct);
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
@@ -1662,6 +1750,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mDisplayInsetsController.removeInsetsChangedListener(mDisplayId, mSplitLayout);
}
+ private void setRootForceTranslucent(boolean translucent, WindowContainerTransaction wct) {
+ if (mIsRootTranslucent == translucent) return;
+
+ mIsRootTranslucent = translucent;
+ wct.setForceTranslucent(mRootTaskInfo.token, translucent);
+ }
+
private void onStageVisibilityChanged(StageListenerImpl stageListener) {
// If split didn't active, just ignore this callback because we should already did these
// on #applyExitSplitScreen.
@@ -1688,16 +1783,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Split entering background.
wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
true /* setReparentLeafTaskIfRelaunch */);
- wct.setForceTranslucent(mRootTaskInfo.token, true);
+ setRootForceTranslucent(true, wct);
} else {
wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
false /* setReparentLeafTaskIfRelaunch */);
+ setRootForceTranslucent(false, wct);
}
mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> {
- setDividerVisibility(mainStageVisible, t);
- });
+ setDividerVisibility(mainStageVisible, null);
}
private void setDividerVisibility(boolean visible, @Nullable SurfaceControl.Transaction t) {
@@ -1720,7 +1814,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mDividerVisible = visible;
sendSplitVisibilityChanged();
- if (mIsSplitEntering) {
+ if (mIsDividerRemoteAnimating) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
" Skip animating divider bar due to it's remote animating.");
return;
@@ -1740,7 +1834,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
" Skip animating divider bar due to divider leash not ready.");
return;
}
- if (mIsSplitEntering) {
+ if (mIsDividerRemoteAnimating) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
" Skip animating divider bar due to it's remote animating.");
return;
@@ -1779,6 +1873,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onAnimationEnd(Animator animation) {
+ if (dividerLeash != null && dividerLeash.isValid()) {
+ transaction.setAlpha(dividerLeash, 1);
+ transaction.apply();
+ }
mTransactionPool.release(transaction);
mDividerFadeInAnimator = null;
}
@@ -1804,7 +1902,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSplitLayout.flingDividerToDismiss(
mSideStagePosition != SPLIT_POSITION_BOTTOM_OR_RIGHT,
EXIT_REASON_APP_FINISHED);
- } else if (!isSplitScreenVisible() && !mIsSplitEntering) {
+ } else if (!isSplitScreenVisible() && mSplitRequest == null) {
+ // Dismiss split screen in the background once any sides of the split become empty.
exitSplitScreen(null /* childrenToTop */, EXIT_REASON_APP_FINISHED);
}
} else if (isSideStage && hasChildren && !mMainStage.isActive()) {
@@ -1820,7 +1919,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mMainStage.activate(wct, true /* includingTopTask */);
updateWindowBounds(mSplitLayout, wct);
wct.reorder(mRootTaskInfo.token, true);
- wct.setForceTranslucent(mRootTaskInfo.token, false);
+ setRootForceTranslucent(false, wct);
}
mSyncQueue.queue(wct);
@@ -2389,6 +2488,20 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
}
+ /** Move the specified task to fullscreen, regardless of focus state. */
+ public void moveTaskToFullscreen(int taskId) {
+ boolean leftOrTop;
+ if (mMainStage.containsTask(taskId)) {
+ leftOrTop = (mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT);
+ } else if (mSideStage.containsTask(taskId)) {
+ leftOrTop = (mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT);
+ } else {
+ return;
+ }
+ mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
+
+ }
+
boolean isLaunchToSplit(TaskInfo taskInfo) {
return getActivateSplitPosition(taskInfo) != SPLIT_POSITION_UNDEFINED;
}
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 0359761388dc..a841b7f96d3c 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
@@ -92,7 +92,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
protected SurfaceControl mDimLayer;
protected SparseArray<ActivityManager.RunningTaskInfo> mChildrenTaskInfo = new SparseArray<>();
private final SparseArray<SurfaceControl> mChildrenLeashes = new SparseArray<>();
- private int mLastVisibleTaskId = INVALID_TASK_ID;
// TODO(b/204308910): Extracts SplitDecorManager related code to common package.
private SplitDecorManager mSplitDecorManager;
@@ -124,13 +123,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
}
/**
- * Returns the last visible task's id.
- */
- int getLastVisibleTaskId() {
- return mLastVisibleTaskId;
- }
-
- /**
* Returns the top visible child task's id.
*/
int getTopVisibleChildTaskId() {
@@ -229,9 +221,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
return;
}
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
- if (taskInfo.isVisible && taskInfo.taskId != mLastVisibleTaskId) {
- mLastVisibleTaskId = taskInfo.taskId;
- }
mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
taskInfo.isVisible);
if (!ENABLE_SHELL_TRANSITIONS) {
@@ -264,9 +253,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
} else if (mChildrenTaskInfo.contains(taskId)) {
mChildrenTaskInfo.remove(taskId);
mChildrenLeashes.remove(taskId);
- if (taskId == mLastVisibleTaskId) {
- mLastVisibleTaskId = INVALID_TASK_ID;
- }
mCallbacks.onChildTaskStatusChanged(taskId, false /* present */, taskInfo.isVisible);
if (ENABLE_SHELL_TRANSITIONS) {
// Status is managed/synchronized by the transition lifecycle.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
index eab82f00e962..e0f3fcd932c2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
@@ -26,8 +26,10 @@ import android.animation.TypeEvaluator;
import android.annotation.NonNull;
import android.app.TaskInfo;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Matrix;
import android.graphics.Rect;
+import android.os.Trace;
import android.util.SparseArray;
import android.view.InsetsSource;
import android.view.InsetsState;
@@ -36,6 +38,8 @@ import android.view.SurfaceControl.Transaction;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.sysui.ConfigurationChangeListener;
+import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.unfold.UnfoldAnimationController;
import com.android.wm.shell.unfold.UnfoldBackgroundController;
@@ -51,7 +55,7 @@ import com.android.wm.shell.unfold.UnfoldBackgroundController;
* instances of FullscreenUnfoldTaskAnimator.
*/
public class FullscreenUnfoldTaskAnimator implements UnfoldTaskAnimator,
- DisplayInsetsController.OnInsetsChangedListener {
+ DisplayInsetsController.OnInsetsChangedListener, ConfigurationChangeListener {
private static final float[] FLOAT_9 = new float[9];
private static final TypeEvaluator<Rect> RECT_EVALUATOR = new RectEvaluator(new Rect());
@@ -63,17 +67,21 @@ public class FullscreenUnfoldTaskAnimator implements UnfoldTaskAnimator,
private final SparseArray<AnimationContext> mAnimationContextByTaskId = new SparseArray<>();
private final int mExpandedTaskBarHeight;
- private final float mWindowCornerRadiusPx;
private final DisplayInsetsController mDisplayInsetsController;
private final UnfoldBackgroundController mBackgroundController;
+ private final Context mContext;
+ private final ShellController mShellController;
private InsetsSource mTaskbarInsetsSource;
+ private float mWindowCornerRadiusPx;
public FullscreenUnfoldTaskAnimator(Context context,
@NonNull UnfoldBackgroundController backgroundController,
- DisplayInsetsController displayInsetsController) {
+ ShellController shellController, DisplayInsetsController displayInsetsController) {
+ mContext = context;
mDisplayInsetsController = displayInsetsController;
mBackgroundController = backgroundController;
+ mShellController = shellController;
mExpandedTaskBarHeight = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.taskbar_frame_height);
mWindowCornerRadiusPx = ScreenDecorationsUtils.getWindowCornerRadius(context);
@@ -81,6 +89,14 @@ public class FullscreenUnfoldTaskAnimator implements UnfoldTaskAnimator,
public void init() {
mDisplayInsetsController.addInsetsChangedListener(DEFAULT_DISPLAY, this);
+ mShellController.addConfigurationChangeListener(this);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfiguration) {
+ Trace.beginSection("FullscreenUnfoldTaskAnimator#onConfigurationChanged");
+ mWindowCornerRadiusPx = ScreenDecorationsUtils.getWindowCornerRadius(mContext);
+ Trace.endSection();
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
index 6e10ebe94c5d..addd0a6012c4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
@@ -28,8 +28,10 @@ import android.animation.RectEvaluator;
import android.animation.TypeEvaluator;
import android.app.TaskInfo;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.Rect;
+import android.os.Trace;
import android.util.SparseArray;
import android.view.InsetsSource;
import android.view.InsetsState;
@@ -42,6 +44,8 @@ import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreen.SplitScreenListener;
import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.sysui.ConfigurationChangeListener;
+import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.unfold.UnfoldAnimationController;
import com.android.wm.shell.unfold.UnfoldBackgroundController;
@@ -62,16 +66,18 @@ import dagger.Lazy;
* They use independent instances of SplitTaskUnfoldAnimator.
*/
public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
- DisplayInsetsController.OnInsetsChangedListener, SplitScreenListener {
+ DisplayInsetsController.OnInsetsChangedListener, SplitScreenListener,
+ ConfigurationChangeListener {
private static final TypeEvaluator<Rect> RECT_EVALUATOR = new RectEvaluator(new Rect());
private static final float CROPPING_START_MARGIN_FRACTION = 0.05f;
+ private final Context mContext;
private final Executor mExecutor;
private final DisplayInsetsController mDisplayInsetsController;
private final SparseArray<AnimationContext> mAnimationContextByTaskId = new SparseArray<>();
private final int mExpandedTaskBarHeight;
- private final float mWindowCornerRadiusPx;
+ private final ShellController mShellController;
private final Lazy<Optional<SplitScreenController>> mSplitScreenController;
private final UnfoldBackgroundController mUnfoldBackgroundController;
@@ -79,6 +85,7 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
private final Rect mSideStageBounds = new Rect();
private final Rect mRootStageBounds = new Rect();
+ private float mWindowCornerRadiusPx;
private InsetsSource mTaskbarInsetsSource;
@SplitPosition
@@ -88,10 +95,12 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
public SplitTaskUnfoldAnimator(Context context, Executor executor,
Lazy<Optional<SplitScreenController>> splitScreenController,
- UnfoldBackgroundController unfoldBackgroundController,
+ ShellController shellController, UnfoldBackgroundController unfoldBackgroundController,
DisplayInsetsController displayInsetsController) {
mDisplayInsetsController = displayInsetsController;
mExecutor = executor;
+ mContext = context;
+ mShellController = shellController;
mUnfoldBackgroundController = unfoldBackgroundController;
mSplitScreenController = splitScreenController;
mExpandedTaskBarHeight = context.getResources().getDimensionPixelSize(
@@ -103,6 +112,14 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
@Override
public void init() {
mDisplayInsetsController.addInsetsChangedListener(DEFAULT_DISPLAY, this);
+ mShellController.addConfigurationChangeListener(this);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfiguration) {
+ Trace.beginSection("SplitTaskUnfoldAnimator#onConfigurationChanged");
+ mWindowCornerRadiusPx = ScreenDecorationsUtils.getWindowCornerRadius(mContext);
+ Trace.endSection();
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 2981f5e160f6..6b7ca421f5ed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -174,7 +174,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
final TaskPositioner taskPositioner =
- new TaskPositioner(mTaskOrganizer, windowDecoration);
+ new TaskPositioner(mTaskOrganizer, windowDecoration, mDisplayController);
final CaptionTouchEventListener touchEventListener =
new CaptionTouchEventListener(taskInfo, taskPositioner);
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
@@ -193,6 +193,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
private final DragDetector mDragDetector;
private int mDragPointerId = -1;
+ private boolean mIsDragging;
private CaptionTouchEventListener(
RunningTaskInfo taskInfo,
@@ -223,19 +224,15 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
if (v.getId() != R.id.caption) {
return false;
}
- mDragDetector.onMotionEvent(e);
-
- if (e.getAction() != MotionEvent.ACTION_DOWN) {
- return false;
- }
- final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
- if (taskInfo.isFocused) {
- return false;
+ if (e.getAction() == MotionEvent.ACTION_DOWN) {
+ final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
+ if (!taskInfo.isFocused) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.reorder(mTaskToken, true /* onTop */);
+ mSyncQueue.queue(wct);
+ }
}
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.reorder(mTaskToken, true /* onTop */);
- mSyncQueue.queue(wct);
- return true;
+ return mDragDetector.onMotionEvent(e);
}
/**
@@ -253,20 +250,24 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
mDragPointerId = e.getPointerId(0);
mDragPositioningCallback.onDragPositioningStart(
0 /* ctrlType */, e.getRawX(0), e.getRawY(0));
- break;
+ mIsDragging = false;
+ return false;
}
case MotionEvent.ACTION_MOVE: {
int dragPointerIdx = e.findPointerIndex(mDragPointerId);
mDragPositioningCallback.onDragPositioningMove(
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
- break;
+ mIsDragging = true;
+ return true;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
int dragPointerIdx = e.findPointerIndex(mDragPointerId);
mDragPositioningCallback.onDragPositioningEnd(
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
- break;
+ final boolean wasDragging = mIsDragging;
+ mIsDragging = false;
+ return wasDragging;
}
}
return true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index de5f2f467e99..dee5f8fa74d8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -20,10 +20,14 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.content.Context;
+import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Looper;
@@ -37,7 +41,6 @@ import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.View;
import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
import androidx.annotation.Nullable;
@@ -50,6 +53,7 @@ import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import java.util.Optional;
@@ -80,6 +84,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
private final InputMonitorFactory mInputMonitorFactory;
private TaskOperations mTaskOperations;
+ private Optional<SplitScreenController> mSplitScreenController;
+
public DesktopModeWindowDecorViewModel(
Context context,
Handler mainHandler,
@@ -88,7 +94,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
DisplayController displayController,
SyncTransactionQueue syncQueue,
Optional<DesktopModeController> desktopModeController,
- Optional<DesktopTasksController> desktopTasksController) {
+ Optional<DesktopTasksController> desktopTasksController,
+ Optional<SplitScreenController> splitScreenController) {
this(
context,
mainHandler,
@@ -98,6 +105,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
syncQueue,
desktopModeController,
desktopTasksController,
+ splitScreenController,
new DesktopModeWindowDecoration.Factory(),
new InputMonitorFactory());
}
@@ -112,6 +120,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
SyncTransactionQueue syncQueue,
Optional<DesktopModeController> desktopModeController,
Optional<DesktopTasksController> desktopTasksController,
+ Optional<SplitScreenController> splitScreenController,
DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
InputMonitorFactory inputMonitorFactory) {
mContext = context;
@@ -120,6 +129,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class);
mTaskOrganizer = taskOrganizer;
mDisplayController = displayController;
+ mSplitScreenController = splitScreenController;
mSyncQueue = syncQueue;
mDesktopModeController = desktopModeController;
mDesktopTasksController = desktopTasksController;
@@ -213,6 +223,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
private final DragPositioningCallback mDragPositioningCallback;
private final DragDetector mDragDetector;
+ private boolean mIsDragging;
private int mDragPointerId = -1;
private DesktopModeTouchEventListener(
@@ -230,6 +241,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
final int id = v.getId();
if (id == R.id.close_window || id == R.id.close_button) {
mTaskOperations.closeTask(mTaskToken);
+ if (mSplitScreenController.isPresent()
+ && mSplitScreenController.get().isSplitScreenVisible()) {
+ int remainingTaskPosition = mTaskId == mSplitScreenController.get()
+ .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT).taskId
+ ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
+ ActivityManager.RunningTaskInfo remainingTask = mSplitScreenController.get()
+ .getTaskInfo(remainingTaskPosition);
+ mSplitScreenController.get().moveTaskToFullscreen(remainingTask.taskId);
+ }
} else if (id == R.id.back_button) {
mTaskOperations.injectBackKey();
} else if (id == R.id.caption_handle) {
@@ -254,26 +274,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
if (id != R.id.caption_handle && id != R.id.desktop_mode_caption) {
return false;
}
- switch (e.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mDragDetector.onMotionEvent(e);
- final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
- if (taskInfo.isFocused) {
- return mDragDetector.isDragEvent();
- }
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.reorder(mTaskToken, true /* onTop */);
- mSyncQueue.queue(wct);
- return false;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- boolean res = mDragDetector.isDragEvent();
- mDragDetector.onMotionEvent(e);
- return res;
- default:
- mDragDetector.onMotionEvent(e);
- return mDragDetector.isDragEvent();
- }
+ return mDragDetector.onMotionEvent(e);
}
/**
@@ -297,13 +298,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
mDragPointerId = e.getPointerId(0);
mDragPositioningCallback.onDragPositioningStart(
0 /* ctrlType */, e.getRawX(0), e.getRawY(0));
- break;
+ mIsDragging = false;
+ return false;
}
case MotionEvent.ACTION_MOVE: {
final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
mDragPositioningCallback.onDragPositioningMove(
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
- break;
+ mIsDragging = true;
+ return true;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
@@ -320,7 +323,9 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
c -> c.moveToFullscreen(taskInfo));
}
}
- break;
+ final boolean wasDragging = mIsDragging;
+ mIsDragging = false;
+ return wasDragging;
}
}
return true;
@@ -401,14 +406,14 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
* @param ev the {@link MotionEvent} received by {@link EventReceiver}
*/
private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
+ final DesktopModeWindowDecoration relevantDecor = getRelevantWindowDecor(ev);
if (DesktopModeStatus.isProto2Enabled()) {
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor == null
- || focusedDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
- handleCaptionThroughStatusBar(ev);
+ if (relevantDecor == null
+ || relevantDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
+ handleCaptionThroughStatusBar(ev, relevantDecor);
}
}
- handleEventOutsideFocusedCaption(ev);
+ handleEventOutsideFocusedCaption(ev, relevantDecor);
// Prevent status bar from reacting to a caption drag.
if (DesktopModeStatus.isProto2Enabled()) {
if (mTransitionDragActive) {
@@ -422,16 +427,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
}
// If an UP/CANCEL action is received outside of caption bounds, turn off handle menu
- private void handleEventOutsideFocusedCaption(MotionEvent ev) {
+ private void handleEventOutsideFocusedCaption(MotionEvent ev,
+ DesktopModeWindowDecoration relevantDecor) {
final int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor == null) {
+ if (relevantDecor == null) {
return;
}
if (!mTransitionDragActive) {
- focusedDecor.closeHandleMenuIfNeeded(ev);
+ relevantDecor.closeHandleMenuIfNeeded(ev);
}
}
}
@@ -441,39 +446,38 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
* Perform caption actions if not able to through normal means.
* Turn on desktop mode if handle is dragged below status bar.
*/
- private void handleCaptionThroughStatusBar(MotionEvent ev) {
+ private void handleCaptionThroughStatusBar(MotionEvent ev,
+ DesktopModeWindowDecoration relevantDecor) {
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
// Begin drag through status bar if applicable.
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor != null) {
+ if (relevantDecor != null) {
boolean dragFromStatusBarAllowed = false;
if (DesktopModeStatus.isProto2Enabled()) {
// In proto2 any full screen task can be dragged to freeform
- dragFromStatusBarAllowed = focusedDecor.mTaskInfo.getWindowingMode()
+ dragFromStatusBarAllowed = relevantDecor.mTaskInfo.getWindowingMode()
== WINDOWING_MODE_FULLSCREEN;
}
- if (dragFromStatusBarAllowed && focusedDecor.checkTouchEventInHandle(ev)) {
+ if (dragFromStatusBarAllowed && relevantDecor.checkTouchEventInHandle(ev)) {
mTransitionDragActive = true;
}
}
break;
}
case MotionEvent.ACTION_UP: {
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor == null) {
+ if (relevantDecor == null) {
mTransitionDragActive = false;
return;
}
if (mTransitionDragActive) {
mTransitionDragActive = false;
final int statusBarHeight = mDisplayController
- .getDisplayLayout(focusedDecor.mTaskInfo.displayId).stableInsets().top;
+ .getDisplayLayout(relevantDecor.mTaskInfo.displayId).stableInsets().top;
if (ev.getY() > statusBarHeight) {
if (DesktopModeStatus.isProto2Enabled()) {
mDesktopTasksController.ifPresent(
- c -> c.moveToDesktop(focusedDecor.mTaskInfo));
+ c -> c.moveToDesktop(relevantDecor.mTaskInfo));
} else if (DesktopModeStatus.isProto1Enabled()) {
mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
}
@@ -481,7 +485,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
return;
}
}
- focusedDecor.checkClickEvent(ev);
+ relevantDecor.checkClickEvent(ev);
break;
}
case MotionEvent.ACTION_CANCEL: {
@@ -491,6 +495,38 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
}
@Nullable
+ private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
+ if (mSplitScreenController.isPresent()
+ && mSplitScreenController.get().isSplitScreenVisible()) {
+ // We can't look at focused task here as only one task will have focus.
+ return getSplitScreenDecor(ev);
+ } else {
+ return getFocusedDecor();
+ }
+ }
+
+ @Nullable
+ private DesktopModeWindowDecoration getSplitScreenDecor(MotionEvent ev) {
+ ActivityManager.RunningTaskInfo topOrLeftTask =
+ mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT);
+ ActivityManager.RunningTaskInfo bottomOrRightTask =
+ mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT);
+ if (topOrLeftTask != null && topOrLeftTask.getConfiguration()
+ .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
+ return mWindowDecorByTaskId.get(topOrLeftTask.taskId);
+ } else if (bottomOrRightTask != null && bottomOrRightTask.getConfiguration()
+ .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
+ Rect bottomOrRightBounds = bottomOrRightTask.getConfiguration().windowConfiguration
+ .getBounds();
+ ev.offsetLocation(-bottomOrRightBounds.left, -bottomOrRightBounds.top);
+ return mWindowDecorByTaskId.get(bottomOrRightTask.taskId);
+ } else {
+ return null;
+ }
+
+ }
+
+ @Nullable
private DesktopModeWindowDecoration getFocusedDecor() {
final int size = mWindowDecorByTaskId.size();
DesktopModeWindowDecoration focusedDecor = null;
@@ -558,7 +594,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
final TaskPositioner taskPositioner =
- new TaskPositioner(mTaskOrganizer, windowDecoration, mDragStartListener);
+ new TaskPositioner(mTaskOrganizer, windowDecoration, mDisplayController,
+ mDragStartListener);
final DesktopModeTouchEventListener touchEventListener =
new DesktopModeTouchEventListener(taskInfo, taskPositioner);
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 245cc8d7ee87..72da1089c91c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -74,6 +74,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
private boolean mDesktopActive;
private AdditionalWindow mHandleMenu;
private final int mHandleMenuWidthId = R.dimen.freeform_decor_caption_menu_width;
+ private final int mHandleMenuShadowRadiusId = R.dimen.caption_menu_shadow_radius;
+ private final int mHandleMenuCornerRadiusId = R.dimen.caption_menu_corner_radius;
private PointF mHandleMenuPosition = new PointF();
DesktopModeWindowDecoration(
@@ -213,6 +215,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
final View handle = caption.findViewById(R.id.caption_handle);
handle.setOnTouchListener(mOnCaptionTouchListener);
handle.setOnClickListener(mOnCaptionButtonClickListener);
+ if (DesktopModeStatus.isProto1Enabled()) {
+ final View back = caption.findViewById(R.id.back_button);
+ back.setOnClickListener(mOnCaptionButtonClickListener);
+ final View close = caption.findViewById(R.id.close_window);
+ close.setOnClickListener(mOnCaptionButtonClickListener);
+ }
updateButtonVisibility();
}
@@ -319,6 +327,14 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
final View handle = caption.findViewById(R.id.caption_handle);
final Drawable handleBackground = handle.getBackground();
handleBackground.setTintList(buttonTintColor);
+ if (DesktopModeStatus.isProto1Enabled()) {
+ final View back = caption.findViewById(R.id.back_button);
+ final Drawable backBackground = back.getBackground();
+ backBackground.setTintList(buttonTintColor);
+ final View close = caption.findViewById(R.id.close_window);
+ final Drawable closeBackground = close.getBackground();
+ closeBackground.setTintList(buttonTintColor);
+ }
}
private void closeDragResizeListener() {
@@ -339,19 +355,16 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
.windowConfiguration.getBounds().width();
final int menuWidth = loadDimensionPixelSize(resources, mHandleMenuWidthId);
final int menuHeight = loadDimensionPixelSize(resources, mCaptionMenuHeightId);
-
- // Elevation gives the appearance of a changed x/y coordinate; this is to fix that
- int elevationOffset = 2 * loadDimensionPixelSize(resources,
- R.dimen.caption_menu_elevation);
+ final int shadowRadius = loadDimensionPixelSize(resources, mHandleMenuShadowRadiusId);
+ final int cornerRadius = loadDimensionPixelSize(resources, mHandleMenuCornerRadiusId);
final int x = mRelayoutParams.mCaptionX + (captionWidth / 2) - (menuWidth / 2)
- - mResult.mDecorContainerOffsetX - elevationOffset;
- final int y =
- mRelayoutParams.mCaptionY - mResult.mDecorContainerOffsetY - elevationOffset;
+ - mResult.mDecorContainerOffsetX;
+ final int y = mRelayoutParams.mCaptionY - mResult.mDecorContainerOffsetY;
mHandleMenuPosition.set(x, y);
String namePrefix = "Caption Menu";
mHandleMenu = addWindow(R.layout.desktop_mode_decor_handle_menu, namePrefix, t, x, y,
- menuWidth, menuHeight, 2 * elevationOffset);
+ menuWidth, menuHeight, shadowRadius, cornerRadius);
mSyncQueue.runInSync(transaction -> {
transaction.merge(t);
t.close();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
index cf1850b92373..65b5a7a17afe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
@@ -56,10 +56,15 @@ class DragDetector {
* {@link #mEventHandler} handles the previous down event if the event shouldn't be passed
*/
boolean onMotionEvent(MotionEvent ev) {
+ final boolean isTouchScreen =
+ (ev.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
+ if (!isTouchScreen) {
+ // Only touches generate noisy moves, so mouse/trackpad events don't need to filtered
+ // to take the slop threshold into consideration.
+ return mEventHandler.handleMotionEvent(ev);
+ }
switch (ev.getActionMasked()) {
case ACTION_DOWN: {
- // Only touch screens generate noisy moves.
- mIsDragEvent = (ev.getSource() & SOURCE_TOUCHSCREEN) != SOURCE_TOUCHSCREEN;
mDragPointerId = ev.getPointerId(0);
float rawX = ev.getRawX(0);
float rawY = ev.getRawY(0);
@@ -72,8 +77,12 @@ class DragDetector {
int dragPointerIndex = ev.findPointerIndex(mDragPointerId);
float dx = ev.getRawX(dragPointerIndex) - mInputDownPoint.x;
float dy = ev.getRawY(dragPointerIndex) - mInputDownPoint.y;
+ // Touches generate noisy moves, so only once the move is past the touch
+ // slop threshold should it be considered a drag.
mIsDragEvent = Math.hypot(dx, dy) > mTouchSlop;
}
+ // The event handler should only be notified about 'move' events if a drag has been
+ // detected.
if (mIsDragEvent) {
return mEventHandler.handleMotionEvent(ev);
} else {
@@ -94,10 +103,6 @@ class DragDetector {
mTouchSlop = touchSlop;
}
- boolean isDragEvent() {
- return mIsDragEvent;
- }
-
private void resetState() {
mIsDragEvent = false;
mInputDownPoint.set(0, 0);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS
new file mode 100644
index 000000000000..4417209b85ed
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS
@@ -0,0 +1 @@
+jorgegil@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
index d3f92277bf03..0bce3acecb3c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
@@ -19,9 +19,11 @@ package com.android.wm.shell.windowdecor;
import android.annotation.IntDef;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.util.DisplayMetrics;
import android.window.WindowContainerTransaction;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
class TaskPositioner implements DragPositioningCallback {
@@ -35,8 +37,10 @@ class TaskPositioner implements DragPositioningCallback {
static final int CTRL_TYPE_BOTTOM = 8;
private final ShellTaskOrganizer mTaskOrganizer;
+ private final DisplayController mDisplayController;
private final WindowDecoration mWindowDecoration;
+ private final Rect mTempBounds = new Rect();
private final Rect mTaskBoundsAtDragStart = new Rect();
private final PointF mRepositionStartPoint = new PointF();
private final Rect mRepositionTaskBounds = new Rect();
@@ -45,14 +49,16 @@ class TaskPositioner implements DragPositioningCallback {
private int mCtrlType;
private DragStartListener mDragStartListener;
- TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration) {
- this(taskOrganizer, windowDecoration, dragStartListener -> {});
+ TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
+ DisplayController displayController) {
+ this(taskOrganizer, windowDecoration, displayController, dragStartListener -> {});
}
TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
- DragStartListener dragStartListener) {
+ DisplayController displayController, DragStartListener dragStartListener) {
mTaskOrganizer = taskOrganizer;
mWindowDecoration = windowDecoration;
+ mDisplayController = displayController;
mDragStartListener = dragStartListener;
}
@@ -112,31 +118,75 @@ class TaskPositioner implements DragPositioningCallback {
final float deltaX = x - mRepositionStartPoint.x;
final float deltaY = y - mRepositionStartPoint.y;
mRepositionTaskBounds.set(mTaskBoundsAtDragStart);
+
+ final Rect stableBounds = mTempBounds;
+ // Make sure the new resizing destination in any direction falls within the stable bounds.
+ // If not, set the bounds back to the old location that was valid to avoid conflicts with
+ // some regions such as the gesture area.
+ mDisplayController.getDisplayLayout(mWindowDecoration.mDisplay.getDisplayId())
+ .getStableBounds(stableBounds);
if ((mCtrlType & CTRL_TYPE_LEFT) != 0) {
- mRepositionTaskBounds.left += deltaX;
+ final int candidateLeft = mRepositionTaskBounds.left + (int) deltaX;
+ mRepositionTaskBounds.left = (candidateLeft > stableBounds.left)
+ ? candidateLeft : oldLeft;
}
if ((mCtrlType & CTRL_TYPE_RIGHT) != 0) {
- mRepositionTaskBounds.right += deltaX;
+ final int candidateRight = mRepositionTaskBounds.right + (int) deltaX;
+ mRepositionTaskBounds.right = (candidateRight < stableBounds.right)
+ ? candidateRight : oldRight;
}
if ((mCtrlType & CTRL_TYPE_TOP) != 0) {
- mRepositionTaskBounds.top += deltaY;
+ final int candidateTop = mRepositionTaskBounds.top + (int) deltaY;
+ mRepositionTaskBounds.top = (candidateTop > stableBounds.top)
+ ? candidateTop : oldTop;
}
if ((mCtrlType & CTRL_TYPE_BOTTOM) != 0) {
- mRepositionTaskBounds.bottom += deltaY;
+ final int candidateBottom = mRepositionTaskBounds.bottom + (int) deltaY;
+ mRepositionTaskBounds.bottom = (candidateBottom < stableBounds.bottom)
+ ? candidateBottom : oldBottom;
}
if (mCtrlType == CTRL_TYPE_UNDEFINED) {
mRepositionTaskBounds.offset((int) deltaX, (int) deltaY);
}
+ // If width or height are negative or less than the minimum width or height, revert the
+ // respective bounds to use previous bound dimensions.
+ if (mRepositionTaskBounds.width() < getMinWidth()) {
+ mRepositionTaskBounds.right = oldRight;
+ mRepositionTaskBounds.left = oldLeft;
+ }
+ if (mRepositionTaskBounds.height() < getMinHeight()) {
+ mRepositionTaskBounds.top = oldTop;
+ mRepositionTaskBounds.bottom = oldBottom;
+ }
+ // If there are no changes to the bounds after checking new bounds against minimum width
+ // and height, do not set bounds and return false
if (oldLeft == mRepositionTaskBounds.left && oldTop == mRepositionTaskBounds.top
&& oldRight == mRepositionTaskBounds.right
&& oldBottom == mRepositionTaskBounds.bottom) {
return false;
}
+
wct.setBounds(mWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
return true;
}
+ private float getMinWidth() {
+ return mWindowDecoration.mTaskInfo.minWidth < 0 ? getDefaultMinSize()
+ : mWindowDecoration.mTaskInfo.minWidth;
+ }
+
+ private float getMinHeight() {
+ return mWindowDecoration.mTaskInfo.minHeight < 0 ? getDefaultMinSize()
+ : mWindowDecoration.mTaskInfo.minHeight;
+ }
+
+ private float getDefaultMinSize() {
+ float density = mDisplayController.getDisplayLayout(mWindowDecoration.mTaskInfo.displayId)
+ .densityDpi() * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+ return mWindowDecoration.mTaskInfo.defaultMinSize * density;
+ }
+
interface DragStartListener {
/**
* Inform the implementing class that a drag resize has started
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index ae685ad4b8d9..133826f3e69b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -391,11 +391,12 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
* @param yPos y position of new window
* @param width width of new window
* @param height height of new window
- * @param cropPadding padding to add to window crop to ensure shadows display properly
- * @return
+ * @param shadowRadius radius of the shadow of the new window
+ * @param cornerRadius radius of the corners of the new window
+ * @return the {@link AdditionalWindow} that was added.
*/
AdditionalWindow addWindow(int layoutId, String namePrefix, SurfaceControl.Transaction t,
- int xPos, int yPos, int width, int height, int cropPadding) {
+ int xPos, int yPos, int width, int height, int shadowRadius, int cornerRadius) {
final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
SurfaceControl windowSurfaceControl = builder
.setName(namePrefix + " of Task=" + mTaskInfo.taskId)
@@ -404,9 +405,10 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
.build();
View v = LayoutInflater.from(mDecorWindowContext).inflate(layoutId, null);
- t.setPosition(
- windowSurfaceControl, xPos, yPos)
- .setWindowCrop(windowSurfaceControl, width + cropPadding, height + cropPadding)
+ t.setPosition(windowSurfaceControl, xPos, yPos)
+ .setWindowCrop(windowSurfaceControl, width, height)
+ .setShadowRadius(windowSurfaceControl, shadowRadius)
+ .setCornerRadius(windowSurfaceControl, cornerRadius)
.show(windowSurfaceControl);
final WindowManager.LayoutParams lp =
new WindowManager.LayoutParams(width, height,
diff --git a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
index fac04614d945..47a116be1b66 100644
--- a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
@@ -20,6 +20,7 @@
package="com.android.wm.shell.tests">
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
+ <uses-permission android:name="android.permission.VIBRATE"/>
<application android:debuggable="true" android:largeHeap="true">
<uses-library android:name="android.test.mock" />
diff --git a/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml b/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
index 27d40b2b25b2..aa1b24189274 100644
--- a/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
@@ -24,4 +24,6 @@
<dimen name="test_window_decor_bottom_outset">40dp</dimen>
<dimen name="test_window_decor_shadow_radius">5dp</dimen>
<dimen name="test_window_decor_resize_handle">10dp</dimen>
+ <dimen name="test_caption_menu_shadow_radius">4dp</dimen>
+ <dimen name="test_caption_menu_corner_radius">20dp</dimen>
</resources> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DevicePostureControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DevicePostureControllerTest.java
new file mode 100644
index 000000000000..f8ee300e411c
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DevicePostureControllerTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.wm.shell.common;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.content.Context;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.sysui.ShellInit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DevicePostureControllerTest {
+ @Mock
+ private Context mContext;
+
+ @Mock
+ private ShellInit mShellInit;
+
+ @Mock
+ private ShellExecutor mMainExecutor;
+
+ @Captor
+ private ArgumentCaptor<Integer> mDevicePostureCaptor;
+
+ @Mock
+ private DevicePostureController.OnDevicePostureChangedListener mOnDevicePostureChangedListener;
+
+ private DevicePostureController mDevicePostureController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mDevicePostureController = new DevicePostureController(mContext, mShellInit, mMainExecutor);
+ }
+
+ @Test
+ public void instantiateController_addInitCallback() {
+ verify(mShellInit, times(1)).addInitCallback(any(), eq(mDevicePostureController));
+ }
+
+ @Test
+ public void registerOnDevicePostureChangedListener_callbackCurrentPosture() {
+ mDevicePostureController.registerOnDevicePostureChangedListener(
+ mOnDevicePostureChangedListener);
+ verify(mOnDevicePostureChangedListener, times(1))
+ .onDevicePostureChanged(anyInt());
+ }
+
+ @Test
+ public void onDevicePostureChanged_differentPosture_callbackListener() {
+ mDevicePostureController.registerOnDevicePostureChangedListener(
+ mOnDevicePostureChangedListener);
+ verify(mOnDevicePostureChangedListener).onDevicePostureChanged(
+ mDevicePostureCaptor.capture());
+ clearInvocations(mOnDevicePostureChangedListener);
+
+ int differentDevicePosture = mDevicePostureCaptor.getValue() + 1;
+ mDevicePostureController.onDevicePostureChanged(differentDevicePosture);
+
+ verify(mOnDevicePostureChangedListener, times(1))
+ .onDevicePostureChanged(differentDevicePosture);
+ }
+
+ @Test
+ public void onDevicePostureChanged_samePosture_doesNotCallbackListener() {
+ mDevicePostureController.registerOnDevicePostureChangedListener(
+ mOnDevicePostureChangedListener);
+ verify(mOnDevicePostureChangedListener).onDevicePostureChanged(
+ mDevicePostureCaptor.capture());
+ clearInvocations(mOnDevicePostureChangedListener);
+
+ int sameDevicePosture = mDevicePostureCaptor.getValue();
+ mDevicePostureController.onDevicePostureChanged(sameDevicePosture);
+
+ verifyZeroInteractions(mOnDevicePostureChangedListener);
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TabletopModeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TabletopModeControllerTest.java
new file mode 100644
index 000000000000..96d202ce3a85
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TabletopModeControllerTest.java
@@ -0,0 +1,270 @@
+/*
+ * 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.wm.shell.common;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_CLOSED;
+import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_HALF_OPENED;
+import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_OPENED;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.Surface;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.TestShellExecutor;
+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;
+
+/**
+ * Tests for {@link TabletopModeController}.
+ */
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class TabletopModeControllerTest extends ShellTestCase {
+ // It's considered tabletop mode if the display rotation angle matches what's in this array.
+ // It's defined as com.android.internal.R.array.config_deviceTabletopRotations on real devices.
+ private static final int[] TABLETOP_MODE_ROTATIONS = new int[] {
+ 90 /* Surface.ROTATION_90 */,
+ 270 /* Surface.ROTATION_270 */
+ };
+
+ private TestShellExecutor mMainExecutor;
+
+ private Configuration mConfiguration;
+
+ private TabletopModeController mPipTabletopController;
+
+ @Mock
+ private Context mContext;
+
+ @Mock
+ private ShellInit mShellInit;
+
+ @Mock
+ private Resources mResources;
+
+ @Mock
+ private DevicePostureController mDevicePostureController;
+
+ @Mock
+ private DisplayController mDisplayController;
+
+ @Mock
+ private TabletopModeController.OnTabletopModeChangedListener mOnTabletopModeChangedListener;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mResources.getIntArray(com.android.internal.R.array.config_deviceTabletopRotations))
+ .thenReturn(TABLETOP_MODE_ROTATIONS);
+ when(mContext.getResources()).thenReturn(mResources);
+ mMainExecutor = new TestShellExecutor();
+ mConfiguration = new Configuration();
+ mPipTabletopController = new TabletopModeController(mContext, mShellInit,
+ mDevicePostureController, mDisplayController, mMainExecutor);
+ mPipTabletopController.onInit();
+ }
+
+ @Test
+ public void instantiateController_addInitCallback() {
+ verify(mShellInit, times(1)).addInitCallback(any(), eq(mPipTabletopController));
+ }
+
+ @Test
+ public void registerOnTabletopModeChangedListener_notInTabletopMode_callbackFalse() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.registerOnTabletopModeChangedListener(
+ mOnTabletopModeChangedListener);
+
+ verify(mOnTabletopModeChangedListener, times(1))
+ .onTabletopModeChanged(false);
+ }
+
+ @Test
+ public void registerOnTabletopModeChangedListener_inTabletopMode_callbackTrue() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.registerOnTabletopModeChangedListener(
+ mOnTabletopModeChangedListener);
+
+ verify(mOnTabletopModeChangedListener, times(1))
+ .onTabletopModeChanged(true);
+ }
+
+ @Test
+ public void registerOnTabletopModeChangedListener_notInTabletopModeTwice_callbackOnce() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.registerOnTabletopModeChangedListener(
+ mOnTabletopModeChangedListener);
+ clearInvocations(mOnTabletopModeChangedListener);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ verifyZeroInteractions(mOnTabletopModeChangedListener);
+ }
+
+ // Test cases starting from folded state (DEVICE_POSTURE_CLOSED)
+ @Test
+ public void foldedRotation90_halfOpen_scheduleTabletopModeChange() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+
+ assertTrue(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+ }
+
+ @Test
+ public void foldedRotation0_halfOpen_noScheduleTabletopModeChange() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+
+ assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+ }
+
+ @Test
+ public void foldedRotation90_halfOpenThenUnfold_cancelTabletopModeChange() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+
+ assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+ }
+
+ @Test
+ public void foldedRotation90_halfOpenThenFold_cancelTabletopModeChange() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+
+ assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+ }
+
+ @Test
+ public void foldedRotation90_halfOpenThenRotate_cancelTabletopModeChange() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+ }
+
+ // Test cases starting from unfolded state (DEVICE_POSTURE_OPENED)
+ @Test
+ public void unfoldedRotation90_halfOpen_scheduleTabletopModeChange() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+
+ assertTrue(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+ }
+
+ @Test
+ public void unfoldedRotation0_halfOpen_noScheduleTabletopModeChange() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+
+ assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+ }
+
+ @Test
+ public void unfoldedRotation90_halfOpenThenUnfold_cancelTabletopModeChange() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+
+ assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+ }
+
+ @Test
+ public void unfoldedRotation90_halfOpenThenFold_cancelTabletopModeChange() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+
+ assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+ }
+
+ @Test
+ public void unfoldedRotation90_halfOpenThenRotate_cancelTabletopModeChange() {
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+ mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+ mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+ assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index 875e6105b7bc..98de58404e80 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -474,6 +474,36 @@ public class CompatUIControllerTest extends ShellTestCase {
verify(mMockRestartDialogLayout).updateVisibility(true);
}
+ @Test
+ public void testRestartLayoutRecreatedIfNeeded() {
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
+ /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ doReturn(true).when(mMockRestartDialogLayout)
+ .needsToBeRecreated(any(TaskInfo.class),
+ any(ShellTaskOrganizer.TaskListener.class));
+
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+
+ verify(mMockRestartDialogLayout, times(2))
+ .createLayout(anyBoolean());
+ }
+
+ @Test
+ public void testRestartLayoutNotRecreatedIfNotNeeded() {
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
+ /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ doReturn(false).when(mMockRestartDialogLayout)
+ .needsToBeRecreated(any(TaskInfo.class),
+ any(ShellTaskOrganizer.TaskListener.class));
+
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+
+ verify(mMockRestartDialogLayout, times(1))
+ .createLayout(anyBoolean());
+ }
+
private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
@CameraCompatControlState int cameraCompatControlState) {
RunningTaskInfo taskInfo = new RunningTaskInfo();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
index b6dbcf204364..523cb6629d9a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
@@ -48,7 +48,6 @@ import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -82,7 +81,7 @@ public class DragAndDropControllerTest extends ShellTestCase {
@Mock
private ShellExecutor mMainExecutor;
@Mock
- private SplitScreenController mSplitScreenController;
+ private WindowManager mWindowManager;
private DragAndDropController mController;
@@ -100,11 +99,6 @@ public class DragAndDropControllerTest extends ShellTestCase {
}
@Test
- public void instantiateController_registerConfigChangeListener() {
- verify(mShellController, times(1)).addConfigurationChangeListener(any());
- }
-
- @Test
public void testIgnoreNonDefaultDisplays() {
final int nonDefaultDisplayId = 12345;
final View dragLayout = mock(View.class);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
index 355072116cb1..1d1aa795173c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
@@ -49,6 +49,7 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopTasksController;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import org.junit.Before;
import org.junit.Test;
@@ -73,6 +74,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase {
@Mock private Choreographer mMainChoreographer;
@Mock private ShellTaskOrganizer mTaskOrganizer;
@Mock private DisplayController mDisplayController;
+ @Mock private SplitScreenController mSplitScreenController;
@Mock private SyncTransactionQueue mSyncQueue;
@Mock private DesktopModeController mDesktopModeController;
@Mock private DesktopTasksController mDesktopTasksController;
@@ -98,6 +100,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase {
mSyncQueue,
Optional.of(mDesktopModeController),
Optional.of(mDesktopTasksController),
+ Optional.of(mSplitScreenController),
mDesktopModeWindowDecorFactory,
mMockInputMonitorFactory
);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
index f185a8a80719..94c064bda763 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
@@ -5,11 +5,16 @@ import android.app.WindowConfiguration
import android.graphics.Rect
import android.os.IBinder
import android.testing.AndroidTestingRunner
+import android.view.Display
import android.window.WindowContainerToken
+import android.window.WindowContainerTransaction
import android.window.WindowContainerTransaction.Change.CHANGE_DRAG_RESIZING
import androidx.test.filters.SmallTest
+import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_BOTTOM
import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_RIGHT
import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_TOP
import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_UNDEFINED
@@ -17,10 +22,11 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.any
import org.mockito.Mockito.argThat
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
/**
@@ -45,6 +51,13 @@ class TaskPositionerTest : ShellTestCase() {
@Mock
private lateinit var taskBinder: IBinder
+ @Mock
+ private lateinit var mockDisplayController: DisplayController
+ @Mock
+ private lateinit var mockDisplayLayout: DisplayLayout
+ @Mock
+ private lateinit var mockDisplay: Display
+
private lateinit var taskPositioner: TaskPositioner
@Before
@@ -54,14 +67,28 @@ class TaskPositionerTest : ShellTestCase() {
taskPositioner = TaskPositioner(
mockShellTaskOrganizer,
mockWindowDecoration,
+ mockDisplayController,
mockDragStartListener
)
+
`when`(taskToken.asBinder()).thenReturn(taskBinder)
+ `when`(mockDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mockDisplayLayout)
+ `when`(mockDisplayLayout.densityDpi()).thenReturn(DENSITY_DPI)
+ `when`(mockDisplayLayout.getStableBounds(any())).thenAnswer { i ->
+ (i.arguments.first() as Rect).set(STABLE_BOUNDS)
+ }
+
mockWindowDecoration.mTaskInfo = ActivityManager.RunningTaskInfo().apply {
taskId = TASK_ID
token = taskToken
+ minWidth = MIN_WIDTH
+ minHeight = MIN_HEIGHT
+ defaultMinSize = DEFAULT_MIN
+ displayId = DISPLAY_ID
configuration.windowConfiguration.bounds = STARTING_BOUNDS
}
+ mockWindowDecoration.mDisplay = mockDisplay
+ `when`(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
}
@Test
@@ -209,8 +236,318 @@ class TaskPositionerTest : ShellTestCase() {
})
}
+ @Test
+ fun testDragResize_resize_setBoundsDoesNotChangeHeightWhenLessThanMin() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Resize to width of 95px and height of 5px with min width of 10px
+ val newX = STARTING_BOUNDS.right.toFloat() - 5
+ val newY = STARTING_BOUNDS.top.toFloat() + 95
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS)
+ != 0) && change.configuration.windowConfiguration.bounds.top ==
+ STARTING_BOUNDS.top &&
+ change.configuration.windowConfiguration.bounds.bottom ==
+ STARTING_BOUNDS.bottom
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_setBoundsDoesNotChangeWidthWhenLessThanMin() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Resize to height of 95px and width of 5px with min width of 10px
+ val newX = STARTING_BOUNDS.right.toFloat() - 95
+ val newY = STARTING_BOUNDS.top.toFloat() + 5
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS)
+ != 0) && change.configuration.windowConfiguration.bounds.right ==
+ STARTING_BOUNDS.right &&
+ change.configuration.windowConfiguration.bounds.left ==
+ STARTING_BOUNDS.left
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_setBoundsDoesNotChangeHeightWhenNegative() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Resize to height of -5px and width of 95px
+ val newX = STARTING_BOUNDS.right.toFloat() - 5
+ val newY = STARTING_BOUNDS.top.toFloat() + 105
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS)
+ != 0) && change.configuration.windowConfiguration.bounds.top ==
+ STARTING_BOUNDS.top &&
+ change.configuration.windowConfiguration.bounds.bottom ==
+ STARTING_BOUNDS.bottom
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_setBoundsDoesNotChangeWidthWhenNegative() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Resize to width of -5px and height of 95px
+ val newX = STARTING_BOUNDS.right.toFloat() - 105
+ val newY = STARTING_BOUNDS.top.toFloat() + 5
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS)
+ != 0) && change.configuration.windowConfiguration.bounds.right ==
+ STARTING_BOUNDS.right &&
+ change.configuration.windowConfiguration.bounds.left ==
+ STARTING_BOUNDS.left
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_setBoundsRunsWhenResizeBoundsValid() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Shrink to height 20px and width 20px with both min height/width equal to 10px
+ val newX = STARTING_BOUNDS.right.toFloat() - 80
+ val newY = STARTING_BOUNDS.top.toFloat() + 80
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_setBoundsDoesNotRunWithNegativeHeightAndWidth() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Shrink to height 5px and width 5px with both min height/width equal to 10px
+ val newX = STARTING_BOUNDS.right.toFloat() - 95
+ val newY = STARTING_BOUNDS.top.toFloat() + 95
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_useDefaultMinWhenMinWidthInvalid() {
+ mockWindowDecoration.mTaskInfo.minWidth = -1
+
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Shrink to width and height of 3px with invalid minWidth = -1 and defaultMinSize = 5px
+ val newX = STARTING_BOUNDS.right.toFloat() - 97
+ val newY = STARTING_BOUNDS.top.toFloat() + 97
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_useMinWidthWhenValid() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Shrink to width and height of 7px with valid minWidth = 10px and defaultMinSize = 5px
+ val newX = STARTING_BOUNDS.right.toFloat() - 93
+ val newY = STARTING_BOUNDS.top.toFloat() + 93
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
+ }
+ })
+ }
+
+ fun testDragResize_toDisallowedBounds_freezesAtLimit() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, // Resize right-bottom corner
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.bottom.toFloat()
+ )
+
+ // Resize the task by 10px to the right and bottom, a valid destination
+ val newBounds = Rect(
+ STARTING_BOUNDS.left,
+ STARTING_BOUNDS.top,
+ STARTING_BOUNDS.right + 10,
+ STARTING_BOUNDS.bottom + 10)
+ taskPositioner.onDragPositioningMove(
+ newBounds.right.toFloat(),
+ newBounds.bottom.toFloat()
+ )
+
+ // Resize the task by another 10px to the right (allowed) and to just in the disallowed
+ // area of the Y coordinate.
+ val newBounds2 = Rect(
+ newBounds.left,
+ newBounds.top,
+ newBounds.right + 10,
+ DISALLOWED_RESIZE_AREA.top
+ )
+ taskPositioner.onDragPositioningMove(
+ newBounds2.right.toFloat(),
+ newBounds2.bottom.toFloat()
+ )
+
+ taskPositioner.onDragPositioningEnd(newBounds2.right.toFloat(), newBounds2.bottom.toFloat())
+
+ // The first resize falls in the allowed area, verify there's a change for it.
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder && change.ofBounds(newBounds)
+ }
+ })
+ // The second resize falls in the disallowed area, verify there's no change for it.
+ verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder && change.ofBounds(newBounds2)
+ }
+ })
+ // Instead, there should be a change for its allowed portion (the X movement) with the Y
+ // staying frozen in the last valid resize position.
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder && change.ofBounds(
+ Rect(
+ newBounds2.left,
+ newBounds2.top,
+ newBounds2.right,
+ newBounds.bottom // Stayed at the first resize destination.
+ )
+ )
+ }
+ })
+ }
+
+ private fun WindowContainerTransaction.Change.ofBounds(bounds: Rect): Boolean {
+ return ((windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0) &&
+ bounds == configuration.windowConfiguration.bounds
+ }
+
companion object {
private const val TASK_ID = 5
+ private const val MIN_WIDTH = 10
+ private const val MIN_HEIGHT = 10
+ private const val DENSITY_DPI = 20
+ private const val DEFAULT_MIN = 40
+ private const val DISPLAY_ID = 1
+ private const val NAVBAR_HEIGHT = 50
+ private val DISPLAY_BOUNDS = Rect(0, 0, 2400, 1600)
private val STARTING_BOUNDS = Rect(0, 0, 100, 100)
+ private val DISALLOWED_RESIZE_AREA = Rect(
+ DISPLAY_BOUNDS.left,
+ DISPLAY_BOUNDS.bottom - NAVBAR_HEIGHT,
+ DISPLAY_BOUNDS.right,
+ DISPLAY_BOUNDS.bottom)
+ private val STABLE_BOUNDS = Rect(
+ DISPLAY_BOUNDS.left,
+ DISPLAY_BOUNDS.top,
+ DISPLAY_BOUNDS.right,
+ DISPLAY_BOUNDS.bottom - NAVBAR_HEIGHT
+ )
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index b80edcece512..7e39b5b8f2ce 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -108,6 +108,8 @@ public class WindowDecorationTests extends ShellTestCase {
private SurfaceControl.Transaction mMockSurfaceControlAddWindowT;
private WindowDecoration.RelayoutParams mRelayoutParams = new WindowDecoration.RelayoutParams();
private int mCaptionMenuWidthId;
+ private int mCaptionMenuShadowRadiusId;
+ private int mCaptionMenuCornerRadiusId;
@Before
public void setUp() {
@@ -118,6 +120,8 @@ public class WindowDecorationTests extends ShellTestCase {
mRelayoutParams.mLayoutResId = 0;
mRelayoutParams.mCaptionHeightId = R.dimen.test_freeform_decor_caption_height;
mCaptionMenuWidthId = R.dimen.test_freeform_decor_caption_menu_width;
+ mCaptionMenuShadowRadiusId = R.dimen.test_caption_menu_shadow_radius;
+ mCaptionMenuCornerRadiusId = R.dimen.test_caption_menu_corner_radius;
mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius;
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
@@ -431,7 +435,19 @@ public class WindowDecorationTests extends ShellTestCase {
verify(additionalWindowSurfaceBuilder).setParent(decorContainerSurface);
verify(additionalWindowSurfaceBuilder).build();
verify(mMockSurfaceControlAddWindowT).setPosition(additionalWindowSurface, 20, 40);
- verify(mMockSurfaceControlAddWindowT).setWindowCrop(additionalWindowSurface, 442, 74);
+ final int width = WindowDecoration.loadDimensionPixelSize(
+ mContext.getResources(), mCaptionMenuWidthId);
+ final int height = WindowDecoration.loadDimensionPixelSize(
+ mContext.getResources(), mRelayoutParams.mCaptionHeightId);
+ verify(mMockSurfaceControlAddWindowT).setWindowCrop(additionalWindowSurface, width, height);
+ final int shadowRadius = WindowDecoration.loadDimensionPixelSize(mContext.getResources(),
+ mCaptionMenuShadowRadiusId);
+ verify(mMockSurfaceControlAddWindowT)
+ .setShadowRadius(additionalWindowSurface, shadowRadius);
+ final int cornerRadius = WindowDecoration.loadDimensionPixelSize(mContext.getResources(),
+ mCaptionMenuCornerRadiusId);
+ verify(mMockSurfaceControlAddWindowT)
+ .setCornerRadius(additionalWindowSurface, cornerRadius);
verify(mMockSurfaceControlAddWindowT).show(additionalWindowSurface);
verify(mMockSurfaceControlViewHostFactory, Mockito.times(2))
.create(any(), eq(defaultDisplay), any());
@@ -559,13 +575,15 @@ public class WindowDecorationTests extends ShellTestCase {
int y = mRelayoutParams.mCaptionY;
int width = loadDimensionPixelSize(resources, mCaptionMenuWidthId);
int height = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionHeightId);
+ int shadowRadius = loadDimensionPixelSize(resources, mCaptionMenuShadowRadiusId);
+ int cornerRadius = loadDimensionPixelSize(resources, mCaptionMenuCornerRadiusId);
String name = "Test Window";
WindowDecoration.AdditionalWindow additionalWindow =
addWindow(R.layout.desktop_mode_decor_handle_menu, name,
mMockSurfaceControlAddWindowT,
x - mRelayoutResult.mDecorContainerOffsetX,
y - mRelayoutResult.mDecorContainerOffsetY,
- width, height, 10);
+ width, height, shadowRadius, cornerRadius);
return additionalWindow;
}
}
diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java
index 5ecec4ddd1ad..3125f088c72b 100644
--- a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java
+++ b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java
@@ -72,6 +72,7 @@ public final class LowLightDreamManager {
public static final int AMBIENT_LIGHT_MODE_LOW_LIGHT = 2;
private final DreamManager mDreamManager;
+ private final LowLightTransitionCoordinator mLowLightTransitionCoordinator;
@Nullable
private final ComponentName mLowLightDreamComponent;
@@ -81,8 +82,10 @@ public final class LowLightDreamManager {
@Inject
public LowLightDreamManager(
DreamManager dreamManager,
+ LowLightTransitionCoordinator lowLightTransitionCoordinator,
@Named(LOW_LIGHT_DREAM_COMPONENT) @Nullable ComponentName lowLightDreamComponent) {
mDreamManager = dreamManager;
+ mLowLightTransitionCoordinator = lowLightTransitionCoordinator;
mLowLightDreamComponent = lowLightDreamComponent;
}
@@ -111,7 +114,9 @@ public final class LowLightDreamManager {
mAmbientLightMode = ambientLightMode;
- mDreamManager.setSystemDreamComponent(mAmbientLightMode == AMBIENT_LIGHT_MODE_LOW_LIGHT
- ? mLowLightDreamComponent : null);
+ boolean shouldEnterLowLight = mAmbientLightMode == AMBIENT_LIGHT_MODE_LOW_LIGHT;
+ mLowLightTransitionCoordinator.notifyBeforeLowLightTransition(shouldEnterLowLight,
+ () -> mDreamManager.setSystemDreamComponent(
+ shouldEnterLowLight ? mLowLightDreamComponent : null));
}
}
diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.java b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.java
new file mode 100644
index 000000000000..874a2d5af75e
--- /dev/null
+++ b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.java
@@ -0,0 +1,111 @@
+/*
+ * 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.dream.lowlight;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.Nullable;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Helper class that allows listening and running animations before entering or exiting low light.
+ */
+@Singleton
+public class LowLightTransitionCoordinator {
+ /**
+ * Listener that is notified before low light entry.
+ */
+ public interface LowLightEnterListener {
+ /**
+ * Callback that is notified before the device enters low light.
+ *
+ * @return an optional animator that will be waited upon before entering low light.
+ */
+ Animator onBeforeEnterLowLight();
+ }
+
+ /**
+ * Listener that is notified before low light exit.
+ */
+ public interface LowLightExitListener {
+ /**
+ * Callback that is notified before the device exits low light.
+ *
+ * @return an optional animator that will be waited upon before exiting low light.
+ */
+ Animator onBeforeExitLowLight();
+ }
+
+ private LowLightEnterListener mLowLightEnterListener;
+ private LowLightExitListener mLowLightExitListener;
+
+ @Inject
+ public LowLightTransitionCoordinator() {
+ }
+
+ /**
+ * Sets the listener for the low light enter event.
+ *
+ * Only one listener can be set at a time. This method will overwrite any previously set
+ * listener. Null can be used to unset the listener.
+ */
+ public void setLowLightEnterListener(@Nullable LowLightEnterListener lowLightEnterListener) {
+ mLowLightEnterListener = lowLightEnterListener;
+ }
+
+ /**
+ * Sets the listener for the low light exit event.
+ *
+ * Only one listener can be set at a time. This method will overwrite any previously set
+ * listener. Null can be used to unset the listener.
+ */
+ public void setLowLightExitListener(@Nullable LowLightExitListener lowLightExitListener) {
+ mLowLightExitListener = lowLightExitListener;
+ }
+
+ /**
+ * Notifies listeners that the device is about to enter or exit low light.
+ *
+ * @param entering true if listeners should be notified before entering low light, false if this
+ * is notifying before exiting.
+ * @param callback callback that will be run after listeners complete.
+ */
+ void notifyBeforeLowLightTransition(boolean entering, Runnable callback) {
+ Animator animator = null;
+
+ if (entering && mLowLightEnterListener != null) {
+ animator = mLowLightEnterListener.onBeforeEnterLowLight();
+ } else if (!entering && mLowLightExitListener != null) {
+ animator = mLowLightExitListener.onBeforeExitLowLight();
+ }
+
+ // If the listener returned an animator to indicate it was running an animation, run the
+ // callback after the animation completes, otherwise call the callback directly.
+ if (animator != null) {
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ callback.run();
+ }
+ });
+ } else {
+ callback.run();
+ }
+ }
+}
diff --git a/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java
index 91a170f7ae14..4b95d8c84bac 100644
--- a/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java
+++ b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java
@@ -21,7 +21,10 @@ import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE
import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE_UNKNOWN;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -44,44 +47,52 @@ public class LowLightDreamManagerTest {
private DreamManager mDreamManager;
@Mock
+ private LowLightTransitionCoordinator mTransitionCoordinator;
+
+ @Mock
private ComponentName mDreamComponent;
+ LowLightDreamManager mLowLightDreamManager;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+
+ // Automatically run any provided Runnable to mTransitionCoordinator to simplify testing.
+ doAnswer(invocation -> {
+ ((Runnable) invocation.getArgument(1)).run();
+ return null;
+ }).when(mTransitionCoordinator).notifyBeforeLowLightTransition(anyBoolean(),
+ any(Runnable.class));
+
+ mLowLightDreamManager = new LowLightDreamManager(mDreamManager, mTransitionCoordinator,
+ mDreamComponent);
}
@Test
public void setAmbientLightMode_lowLight_setSystemDream() {
- final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
- mDreamComponent);
-
- lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
+ mLowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
+ verify(mTransitionCoordinator).notifyBeforeLowLightTransition(eq(true), any());
verify(mDreamManager).setSystemDreamComponent(mDreamComponent);
}
@Test
public void setAmbientLightMode_regularLight_clearSystemDream() {
- final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
- mDreamComponent);
-
- lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_REGULAR);
+ mLowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_REGULAR);
+ verify(mTransitionCoordinator).notifyBeforeLowLightTransition(eq(false), any());
verify(mDreamManager).setSystemDreamComponent(null);
}
@Test
public void setAmbientLightMode_defaultUnknownMode_clearSystemDream() {
- final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
- mDreamComponent);
-
// Set to low light first.
- lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
+ mLowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
clearInvocations(mDreamManager);
// Return to default unknown mode.
- lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_UNKNOWN);
+ mLowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_UNKNOWN);
verify(mDreamManager).setSystemDreamComponent(null);
}
@@ -89,7 +100,7 @@ public class LowLightDreamManagerTest {
@Test
public void setAmbientLightMode_dreamComponentNotSet_doNothing() {
final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
- null /*dream component*/);
+ mTransitionCoordinator, null /*dream component*/);
lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
diff --git a/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.java b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.java
new file mode 100644
index 000000000000..81e1e33d6220
--- /dev/null
+++ b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.dream.lowlight;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.animation.Animator;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class LowLightTransitionCoordinatorTest {
+ @Mock
+ private LowLightTransitionCoordinator.LowLightEnterListener mEnterListener;
+
+ @Mock
+ private LowLightTransitionCoordinator.LowLightExitListener mExitListener;
+
+ @Mock
+ private Animator mAnimator;
+
+ @Captor
+ private ArgumentCaptor<Animator.AnimatorListener> mAnimatorListenerCaptor;
+
+ @Mock
+ private Runnable mRunnable;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void onEnterCalledOnListeners() {
+ LowLightTransitionCoordinator coordinator = new LowLightTransitionCoordinator();
+
+ coordinator.setLowLightEnterListener(mEnterListener);
+
+ coordinator.notifyBeforeLowLightTransition(true, mRunnable);
+
+ verify(mEnterListener).onBeforeEnterLowLight();
+ verify(mRunnable).run();
+ }
+
+ @Test
+ public void onExitCalledOnListeners() {
+ LowLightTransitionCoordinator coordinator = new LowLightTransitionCoordinator();
+
+ coordinator.setLowLightExitListener(mExitListener);
+
+ coordinator.notifyBeforeLowLightTransition(false, mRunnable);
+
+ verify(mExitListener).onBeforeExitLowLight();
+ verify(mRunnable).run();
+ }
+
+ @Test
+ public void listenerNotCalledAfterRemoval() {
+ LowLightTransitionCoordinator coordinator = new LowLightTransitionCoordinator();
+
+ coordinator.setLowLightEnterListener(mEnterListener);
+ coordinator.setLowLightEnterListener(null);
+
+ coordinator.notifyBeforeLowLightTransition(true, mRunnable);
+
+ verifyZeroInteractions(mEnterListener);
+ verify(mRunnable).run();
+ }
+
+ @Test
+ public void runnableCalledAfterAnimationEnds() {
+ when(mEnterListener.onBeforeEnterLowLight()).thenReturn(mAnimator);
+
+ LowLightTransitionCoordinator coordinator = new LowLightTransitionCoordinator();
+ coordinator.setLowLightEnterListener(mEnterListener);
+
+ coordinator.notifyBeforeLowLightTransition(true, mRunnable);
+
+ // Animator listener is added and the runnable is not run yet.
+ verify(mAnimator).addListener(mAnimatorListenerCaptor.capture());
+ verifyZeroInteractions(mRunnable);
+
+ // Runnable is run once the animation ends.
+ mAnimatorListenerCaptor.getValue().onAnimationEnd(null);
+ verify(mRunnable).run();
+ }
+}
diff --git a/media/java/android/media/projection/OWNERS b/media/java/android/media/projection/OWNERS
index 9ca391013aa3..2273f816ac60 100644
--- a/media/java/android/media/projection/OWNERS
+++ b/media/java/android/media/projection/OWNERS
@@ -1,2 +1,4 @@
michaelwr@google.com
santoscordon@google.com
+chaviw@google.com
+nmusgrave@google.com
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
index 33872ed63b89..0da5de75548c 100644
--- a/media/tests/MediaFrameworkTest/AndroidManifest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -37,7 +37,6 @@
</activity>
<activity android:label="Camera2CtsActivity"
android:name="Camera2SurfaceViewActivity"
- android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation|screenSize">
</activity>
</application>
diff --git a/packages/AppPredictionLib/Android.bp b/packages/AppPredictionLib/Android.bp
index 5a68fdc9ae75..31c193631602 100644
--- a/packages/AppPredictionLib/Android.bp
+++ b/packages/AppPredictionLib/Android.bp
@@ -25,7 +25,7 @@ android_library {
name: "app_prediction",
sdk_version: "system_current",
- min_sdk_version: "system_current",
+ min_sdk_version: "current",
srcs: [
"src/**/*.java",
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index 43066140eeb8..854bbb5fa39a 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/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">"Companion Device Manager"</string>
+ <string name="app_label" msgid="4470785958457506021">"Trình quản lý thiết bị đồng hành"</string>
<string name="confirmation_title" msgid="3785000297483688997">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; truy cập &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; của bạn"</string>
<string name="profile_name_watch" msgid="576290739483672360">"đồng hồ"</string>
<string name="chooser_title" msgid="2262294130493605839">"Chọn một <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sẽ do &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; quản lý"</string>
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 87e61b527477..d253dda61e5b 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -65,7 +65,7 @@ android_library {
"src/**/*.kt",
],
- min_sdk_version: "29",
+ min_sdk_version: "30",
}
diff --git a/packages/SettingsLib/DeviceStateRotationLock/OWNERS b/packages/SettingsLib/DeviceStateRotationLock/OWNERS
new file mode 100644
index 000000000000..091df2610866
--- /dev/null
+++ b/packages/SettingsLib/DeviceStateRotationLock/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/packages/SettingsLib/src/com/android/settingslib/devicestate/OWNERS \ No newline at end of file
diff --git a/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
index 4ed7e19f341d..10b004e1b243 100644
--- a/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
+++ b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
@@ -29,6 +29,7 @@ import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.SparseIntArray;
@@ -36,6 +37,7 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -57,6 +59,7 @@ public final class DeviceStateRotationLockSettingsManager {
private final SecureSettings mSecureSettings;
private String[] mDeviceStateRotationLockDefaults;
private SparseIntArray mDeviceStateRotationLockSettings;
+ private SparseIntArray mDeviceStateDefaultRotationLockSettings;
private SparseIntArray mDeviceStateRotationLockFallbackSettings;
private String mLastSettingValue;
private List<SettableDeviceState> mSettableDeviceStates;
@@ -93,9 +96,7 @@ public final class DeviceStateRotationLockSettingsManager {
/** Returns true if device-state based rotation lock settings are enabled. */
public static boolean isDeviceStateRotationLockEnabled(Context context) {
return context.getResources()
- .getStringArray(R.array.config_perDeviceStateRotationLockDefaults)
- .length
- > 0;
+ .getStringArray(R.array.config_perDeviceStateRotationLockDefaults).length > 0;
}
private void listenForSettingsChange() {
@@ -228,6 +229,15 @@ public final class DeviceStateRotationLockSettingsManager {
try {
key = Integer.parseInt(values[i++]);
value = Integer.parseInt(values[i++]);
+ boolean isPersistedValueIgnored = value == DEVICE_STATE_ROTATION_LOCK_IGNORED;
+ boolean isDefaultValueIgnored = mDeviceStateDefaultRotationLockSettings.get(key)
+ == DEVICE_STATE_ROTATION_LOCK_IGNORED;
+ if (isPersistedValueIgnored != isDefaultValueIgnored) {
+ Log.w(TAG, "Conflict for ignored device state " + key
+ + ". Falling back on defaults");
+ fallbackOnDefaults();
+ return;
+ }
mDeviceStateRotationLockSettings.put(key, value);
} catch (NumberFormatException e) {
Log.wtf(TAG, "Error deserializing one of the saved settings", e);
@@ -276,6 +286,9 @@ public final class DeviceStateRotationLockSettingsManager {
}
private void persistSettingIfChanged(String newSettingValue) {
+ Log.v(TAG, "persistSettingIfChanged: "
+ + "last=" + mLastSettingValue + ", "
+ + "new=" + newSettingValue);
if (TextUtils.equals(mLastSettingValue, newSettingValue)) {
return;
}
@@ -288,6 +301,8 @@ public final class DeviceStateRotationLockSettingsManager {
private void loadDefaults() {
mSettableDeviceStates = new ArrayList<>(mDeviceStateRotationLockDefaults.length);
+ mDeviceStateDefaultRotationLockSettings = new SparseIntArray(
+ mDeviceStateRotationLockDefaults.length);
mDeviceStateRotationLockSettings = new SparseIntArray(
mDeviceStateRotationLockDefaults.length);
mDeviceStateRotationLockFallbackSettings = new SparseIntArray(1);
@@ -311,6 +326,7 @@ public final class DeviceStateRotationLockSettingsManager {
boolean isSettable = rotationLockSetting != DEVICE_STATE_ROTATION_LOCK_IGNORED;
mSettableDeviceStates.add(new SettableDeviceState(deviceState, isSettable));
mDeviceStateRotationLockSettings.put(deviceState, rotationLockSetting);
+ mDeviceStateDefaultRotationLockSettings.put(deviceState, rotationLockSetting);
} catch (NumberFormatException e) {
Log.wtf(TAG, "Error parsing settings entry. Entry was: " + entry, e);
return;
@@ -318,6 +334,22 @@ public final class DeviceStateRotationLockSettingsManager {
}
}
+ /** Dumps internal state. */
+ public void dump(IndentingPrintWriter pw) {
+ pw.println("DeviceStateRotationLockSettingsManager");
+ pw.increaseIndent();
+ pw.println("mDeviceStateRotationLockDefaults: " + Arrays.toString(
+ mDeviceStateRotationLockDefaults));
+ pw.println("mDeviceStateDefaultRotationLockSettings: "
+ + mDeviceStateDefaultRotationLockSettings);
+ pw.println("mDeviceStateRotationLockSettings: " + mDeviceStateRotationLockSettings);
+ pw.println("mDeviceStateRotationLockFallbackSettings: "
+ + mDeviceStateRotationLockFallbackSettings);
+ pw.println("mSettableDeviceStates: " + mSettableDeviceStates);
+ pw.println("mLastSettingValue: " + mLastSettingValue);
+ pw.decreaseIndent();
+ }
+
/**
* Called when the persisted settings have changed, requiring a reinitialization of the
* in-memory map.
@@ -372,5 +404,13 @@ public final class DeviceStateRotationLockSettingsManager {
public int hashCode() {
return Objects.hash(mDeviceState, mIsSettable);
}
+
+ @Override
+ public String toString() {
+ return "SettableDeviceState{"
+ + "mDeviceState=" + mDeviceState
+ + ", mIsSettable=" + mIsSettable
+ + '}';
+ }
}
}
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index a28340e168fc..bcc2b67289f3 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Klein"</item>
+ <item msgid="1484561228522634915">"Verstek"</item>
+ <item msgid="4014311587094503943">"Groot"</item>
+ <item msgid="2904569270831156685">"Grootste"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 6d8bf5fe9012..6aa00dfe507f 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -532,7 +532,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wekkers en onthounotas"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Laat toe dat wekkers en onthounotas gestel word"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en onthounotas"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie program toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die program op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie program geskeduleer is, nie werk nie."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie app toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die app op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie app geskeduleer is, nie werk nie."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"skedule, wekker, onthounota, horlosie"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Skakel aan"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Skakel Moenie steur nie aan"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index a201ab093ebe..4e97d478bc41 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"ትንሽ"</item>
+ <item msgid="1484561228522634915">"ነባሪ"</item>
+ <item msgid="4014311587094503943">"ትልቅ"</item>
+ <item msgid="2904569270831156685">"በጣም ትልቅ"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index 7852b0429775..27a236b42cc6 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"صغير"</item>
+ <item msgid="1484561228522634915">"تلقائي"</item>
+ <item msgid="4014311587094503943">"كبير"</item>
+ <item msgid="2904569270831156685">"أكبر حجمًا"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index b273d8ea8276..1a35e7ad4407 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"সৰু"</item>
+ <item msgid="1484561228522634915">"ডিফ’ল্ট"</item>
+ <item msgid="4014311587094503943">"ডাঙৰ"</item>
+ <item msgid="2904569270831156685">"আটাইতকৈ ডাঙৰ"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index dc8be1d550b1..105cc2cd1a98 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Kiçik"</item>
+ <item msgid="1484561228522634915">"Defolt"</item>
+ <item msgid="4014311587094503943">"Böyük"</item>
+ <item msgid="2904569270831156685">"Ən böyük"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 2fc7afbb3e2f..0a2235a81739 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Malo"</item>
+ <item msgid="1484561228522634915">"Podrazumevano"</item>
+ <item msgid="4014311587094503943">"Veliko"</item>
+ <item msgid="2904569270831156685">"Najveće"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index e180b44c5c53..8dcf2b5fbc9f 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Дробны"</item>
+ <item msgid="1484561228522634915">"Стандартны"</item>
+ <item msgid="4014311587094503943">"Вялікі"</item>
+ <item msgid="2904569270831156685">"Найвялікшы"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index cdad4ace231c..4e22cd3842e1 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Малък"</item>
+ <item msgid="1484561228522634915">"По подразбиране"</item>
+ <item msgid="4014311587094503943">"Голям"</item>
+ <item msgid="2904569270831156685">"Най-голям"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index 0d79aa7dc52a..5a2333b2829d 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"কম"</item>
+ <item msgid="1484561228522634915">"ডিফল্ট"</item>
+ <item msgid="4014311587094503943">"বেশি"</item>
+ <item msgid="2904569270831156685">"সবচেয়ে বড়"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index f39f7fc1779d..9ee3bcf75a3f 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -532,7 +532,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi i podsjetnici"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Dozvoli postavljanje alarma i podsjetnika"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu koje je ova aplikacija zakazala neće funkcionirati."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu, a koje je ova aplikacija zakazala, neće funkcionirati."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"raspored, alarm, podsjetnik, sat"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključi način rada Ne ometaj"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index e0bfec50d1c3..d4cccbf8062b 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Petit"</item>
+ <item msgid="1484561228522634915">"Predeterminat"</item>
+ <item msgid="4014311587094503943">"Gran"</item>
+ <item msgid="2904569270831156685">"Més gran possible"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 516a86457967..5caab29acce2 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -532,7 +532,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes i recordatoris"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permet la configuració d\'alarmes i recordatoris"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes i recordatoris"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions a una hora determinada. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programació, alarma, recordatori, rellotge"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activa"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activa el mode No molestis"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index f8cdb6817ec4..f6aae2b30dba 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Malé"</item>
+ <item msgid="1484561228522634915">"Výchozí"</item>
+ <item msgid="4014311587094503943">"Velké"</item>
+ <item msgid="2904569270831156685">"Největší"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 4d656cadefd3..fac21c722233 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Lille"</item>
+ <item msgid="1484561228522634915">"Standard"</item>
+ <item msgid="4014311587094503943">"Stor"</item>
+ <item msgid="2904569270831156685">"Størst"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index 250f0e4e6ad7..ce759c886524 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Klein"</item>
+ <item msgid="1484561228522634915">"Normal"</item>
+ <item msgid="4014311587094503943">"Groß"</item>
+ <item msgid="2904569270831156685">"Extragroß"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index cb6e2e9e011f..80219e422787 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Μικρό"</item>
+ <item msgid="1484561228522634915">"Προεπιλογή"</item>
+ <item msgid="4014311587094503943">"Μεγάλο"</item>
+ <item msgid="2904569270831156685">"Μεγαλύτερο"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index 5769c8dc98dd..96bca9d644df 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Pequeño"</item>
+ <item msgid="1484561228522634915">"Predeterminado"</item>
+ <item msgid="4014311587094503943">"Grande"</item>
+ <item msgid="2904569270831156685">"Máxima"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index e2d9d331a15b..2788a3f23445 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Pequeño"</item>
+ <item msgid="1484561228522634915">"Predeterminado"</item>
+ <item msgid="4014311587094503943">"Grande"</item>
+ <item msgid="2904569270831156685">"El más grande"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index fe97f345229f..753ce734a1c3 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -182,7 +182,7 @@
<string name="unknown" msgid="3544487229740637809">"Desconocido"</string>
<string name="running_process_item_user_label" msgid="3988506293099805796">"Usuario: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="3631650616557252926">"Se han establecido algunos valores predeterminados"</string>
- <string name="launch_defaults_none" msgid="8049374306261262709">"No se han establecido valores predeterminados"</string>
+ <string name="launch_defaults_none" msgid="8049374306261262709">"No hay valores predeterminados"</string>
<string name="tts_settings" msgid="8130616705989351312">"Ajustes de conversión de texto a voz"</string>
<string name="tts_settings_title" msgid="7602210956640483039">"Salida de conversión de texto a voz"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"Velocidad de la voz"</string>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index cd07db1980fb..9e494c98c2ec 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Väike"</item>
+ <item msgid="1484561228522634915">"Vaikeseade"</item>
+ <item msgid="4014311587094503943">"Suur"</item>
+ <item msgid="2904569270831156685">"Suurim"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index 35424c042507..8d23acad31ce 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Txikia"</item>
+ <item msgid="1484561228522634915">"Lehenetsia"</item>
+ <item msgid="4014311587094503943">"Handia"</item>
+ <item msgid="2904569270831156685">"Handiena"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 34e59f31fb3f..a37b500ac5de 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -532,7 +532,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmak eta abisuak"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Eman alarmak eta abisuak ezartzeko baimena"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmak eta abisuak"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nEz baduzu ematen baimen hori, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nBaimen hori ematen ez baduzu, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programazioa, alarma, abisua, erlojua"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktibatu"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu ez molestatzeko modua"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index a3a6e48e0c97..ca4d1c9ee386 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"کوچک"</item>
+ <item msgid="1484561228522634915">"پیش‌فرض"</item>
+ <item msgid="4014311587094503943">"بزرگ"</item>
+ <item msgid="2904569270831156685">"بزرگ‌ترین"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index c7862e3ef961..cd4e16a07ed9 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Pieni"</item>
+ <item msgid="1484561228522634915">"Oletus"</item>
+ <item msgid="4014311587094503943">"Suuri"</item>
+ <item msgid="2904569270831156685">"Suurin"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 70481476bb5b..69669ddbb388 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Petite"</item>
+ <item msgid="1484561228522634915">"Par défaut"</item>
+ <item msgid="4014311587094503943">"Grande"</item>
+ <item msgid="2904569270831156685">"La plus grande"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 43274bb9fa86..411150880a78 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Petit"</item>
+ <item msgid="1484561228522634915">"Par défaut"</item>
+ <item msgid="4014311587094503943">"Grand"</item>
+ <item msgid="2904569270831156685">"Très grand"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index e8c5463b20be..2744a7014a10 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Pequeno"</item>
+ <item msgid="1484561228522634915">"Predeterminado"</item>
+ <item msgid="4014311587094503943">"Grande"</item>
+ <item msgid="2904569270831156685">"O máis grande"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index ac485e11573a..e1cd0567be47 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"નાનું"</item>
+ <item msgid="1484561228522634915">"ડિફૉલ્ટ"</item>
+ <item msgid="4014311587094503943">"મોટું"</item>
+ <item msgid="2904569270831156685">"સૌથી મોટું"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index e7f68d99d509..be92797e2de8 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"छोटा"</item>
+ <item msgid="1484561228522634915">"डिफ़ॉल्ट"</item>
+ <item msgid="4014311587094503943">"बड़ा"</item>
+ <item msgid="2904569270831156685">"सबसे बड़ा"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 28ae1b681010..58b65d1a1504 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Kicsi"</item>
+ <item msgid="1484561228522634915">"Alapértelmezett"</item>
+ <item msgid="4014311587094503943">"Nagy"</item>
+ <item msgid="2904569270831156685">"Legnagyobb"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 5787215418dc..9fa4a10f6590 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Փոքր"</item>
+ <item msgid="1484561228522634915">"Կանխադրված"</item>
+ <item msgid="4014311587094503943">"Մեծ"</item>
+ <item msgid="2904569270831156685">"Շատ մեծ"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 6bb7e5d243b9..eadba8efe708 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Kecil"</item>
+ <item msgid="1484561228522634915">"Default"</item>
+ <item msgid="4014311587094503943">"Besar"</item>
+ <item msgid="2904569270831156685">"Terbesar"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 87433b712e7d..dc08b1f0f7d1 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Lítið"</item>
+ <item msgid="1484561228522634915">"Sjálfgefið"</item>
+ <item msgid="4014311587094503943">"Stórt"</item>
+ <item msgid="2904569270831156685">"Stærst"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index e68adb9e79d1..e91a7bf03642 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Piccolo"</item>
+ <item msgid="1484561228522634915">"Predefinito"</item>
+ <item msgid="4014311587094503943">"Grande"</item>
+ <item msgid="2904569270831156685">"Più grande"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 6dd176574b79..c19b8213ec98 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"קטן"</item>
+ <item msgid="1484561228522634915">"ברירת מחדל"</item>
+ <item msgid="4014311587094503943">"גדול"</item>
+ <item msgid="2904569270831156685">"הכי גדול"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index 385cfc904daf..41ec7ab647bf 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"小"</item>
+ <item msgid="1484561228522634915">"デフォルト"</item>
+ <item msgid="4014311587094503943">"大"</item>
+ <item msgid="2904569270831156685">"最大"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index e800d458b228..54066790e247 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"პატარა"</item>
+ <item msgid="1484561228522634915">"ნაგულისხმევი"</item>
+ <item msgid="4014311587094503943">"დიდი"</item>
+ <item msgid="2904569270831156685">"უდიდესი"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index fa828525276b..68caf967167c 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Кіші"</item>
+ <item msgid="1484561228522634915">"Әдепкі"</item>
+ <item msgid="4014311587094503943">"Үлкен"</item>
+ <item msgid="2904569270831156685">"Ең үлкен"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index 52d82072d132..2f2208427595 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"តូច"</item>
+ <item msgid="1484561228522634915">"លំនាំដើម"</item>
+ <item msgid="4014311587094503943">"ធំ"</item>
+ <item msgid="2904569270831156685">"ធំបំផុត"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 1ad0948924c0..b4fbb3918a5d 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"ಚಿಕ್ಕದು"</item>
+ <item msgid="1484561228522634915">"ಡೀಫಾಲ್ಟ್"</item>
+ <item msgid="4014311587094503943">"ದೊಡ್ಡದು"</item>
+ <item msgid="2904569270831156685">"ಅತಿ ದೊಡ್ಡದು"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 6e00b10820a4..02b3e805dc54 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"작게"</item>
+ <item msgid="1484561228522634915">"기본"</item>
+ <item msgid="4014311587094503943">"크게"</item>
+ <item msgid="2904569270831156685">"가장 크게"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index ec37e64758c6..08781dba0d7b 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Кичине"</item>
+ <item msgid="1484561228522634915">"Демейки"</item>
+ <item msgid="4014311587094503943">"Чоң"</item>
+ <item msgid="2904569270831156685">"Эң чоң"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 3fe8330e05a6..4468b37eb328 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"ນ້ອຍ"</item>
+ <item msgid="1484561228522634915">"ຄ່າເລີ່ມຕົ້ນ"</item>
+ <item msgid="4014311587094503943">"ໃຫຍ່"</item>
+ <item msgid="2904569270831156685">"ໃຫຍ່ທີ່ສຸດ"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index 6b34af34866f..75f97d01dd3b 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Mažas"</item>
+ <item msgid="1484561228522634915">"Numatytasis"</item>
+ <item msgid="4014311587094503943">"Didelis"</item>
+ <item msgid="2904569270831156685">"Didžiausias"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 16f107081f7a..2758dd641e10 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Mazs"</item>
+ <item msgid="1484561228522634915">"Noklusējuma"</item>
+ <item msgid="4014311587094503943">"Liels"</item>
+ <item msgid="2904569270831156685">"Vislielākais"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index d8b86be11b73..3c7b350a096a 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Мал"</item>
+ <item msgid="1484561228522634915">"Стандарден"</item>
+ <item msgid="4014311587094503943">"Голем"</item>
+ <item msgid="2904569270831156685">"Најголем"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index bf6c67a8eb0d..865939316404 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"ചെറുത്"</item>
+ <item msgid="1484561228522634915">"ഡിഫോൾട്ട്"</item>
+ <item msgid="4014311587094503943">"വലുത്"</item>
+ <item msgid="2904569270831156685">"ഏറ്റവും വലുത്"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index 776c5c3f111e..e37636767fde 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Жижиг"</item>
+ <item msgid="1484561228522634915">"Өгөгдмөл"</item>
+ <item msgid="4014311587094503943">"Том"</item>
+ <item msgid="2904569270831156685">"Хамгийн том"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 8b36c73f4f81..f3e78ce92947 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"लहान"</item>
+ <item msgid="1484561228522634915">"डीफॉल्ट"</item>
+ <item msgid="4014311587094503943">"मोठा"</item>
+ <item msgid="2904569270831156685">"सर्वात मोठा"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index 2a1303bf5b6f..825ace769cbb 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Kecil"</item>
+ <item msgid="1484561228522634915">"Lalai"</item>
+ <item msgid="4014311587094503943">"Besar"</item>
+ <item msgid="2904569270831156685">"Terbesar"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index 332dba045a43..fdf64e1675e4 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"သေး"</item>
+ <item msgid="1484561228522634915">"မူရင်း"</item>
+ <item msgid="4014311587094503943">"ကြီး"</item>
+ <item msgid="2904569270831156685">"အကြီးဆုံး"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 80916e373acd..a76307447130 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Liten"</item>
+ <item msgid="1484561228522634915">"Standard"</item>
+ <item msgid="4014311587094503943">"Stor"</item>
+ <item msgid="2904569270831156685">"Størst"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index decf4f5b8212..b079227af256 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"सानो"</item>
+ <item msgid="1484561228522634915">"डिफल्ट"</item>
+ <item msgid="4014311587094503943">"ठुलो"</item>
+ <item msgid="2904569270831156685">"सबैभन्दा ठुलो"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 779515894503..22b4fbf631da 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -530,7 +530,7 @@
<string name="okay" msgid="949938843324579502">"ठिक छ"</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_switch_title" msgid="4939393911531826222">"अलार्म तथा रिमाइन्डर सेट गर्ने अनुमति दिनुहोस्"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म तथा रिमाइन्डर"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"यो एपलाई अलार्म सेट गर्ने र समयमै पूरा गर्नु पर्ने कारबाहीहरूको रुटिन बनाउने अनुमति दिनुहोस्। यो अनुमति दिइएको छ भने यो एप ब्याकग्राउन्डमा चल्छ र धेरै ब्याट्री खपत हुन्छ।\n\nयो अनुमति दिइएको छैन भने सेट गरिएका अलार्म बज्दैनन् र यो एपले तय गरेका गतिविधि चल्दैनन्।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"समयतालिका, अलार्म, रिमाइन्डर, घडी"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index e827be16bcd4..2dc107545615 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Klein"</item>
+ <item msgid="1484561228522634915">"Standaard"</item>
+ <item msgid="4014311587094503943">"Groot"</item>
+ <item msgid="2904569270831156685">"Grootst"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index fc783f037b71..b86d4f290b79 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"ଛୋଟ"</item>
+ <item msgid="1484561228522634915">"ଡିଫଲ୍ଟ"</item>
+ <item msgid="4014311587094503943">"ବଡ଼"</item>
+ <item msgid="2904569270831156685">"ସବୁଠାରୁ ବଡ଼"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index f0e839683054..4135a3078e2d 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"ਛੋਟਾ"</item>
+ <item msgid="1484561228522634915">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ"</item>
+ <item msgid="4014311587094503943">"ਵੱਡਾ"</item>
+ <item msgid="2904569270831156685">"ਸਭ ਤੋਂ ਵੱਡਾ"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index c2be21d93e64..830c7323570a 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Mały"</item>
+ <item msgid="1484561228522634915">"Domyślny"</item>
+ <item msgid="4014311587094503943">"Duży"</item>
+ <item msgid="2904569270831156685">"Największy"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index b18d81973536..96f845e58818 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -532,7 +532,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmy i przypomnienia"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Zezwalaj na ustawianie alarmów i przypomnień"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmy i przypomnienia"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwól na ustawianie alarmów i planowanie innych działań, w przypadku których czas jest istotny. Dzięki temu aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tych uprawnień, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwalaj tej aplikacji na ustawianie alarmów i planowanie działań, w przypadku których czas jest istotny. Aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tego uprawnienia, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"harmonogram, alarm, przypomnienie, zegar"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Włącz"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Włącz tryb Nie przeszkadzać"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index 658b15307f47..5cbca900c8bb 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Pequeno"</item>
+ <item msgid="1484561228522634915">"Padrão"</item>
+ <item msgid="4014311587094503943">"Grande"</item>
+ <item msgid="2904569270831156685">"Maior"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 816108e52bcf..da7dcc5fa268 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -532,7 +532,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 758bc327d09a..f70fae0223f0 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -151,7 +151,7 @@
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Cancelar"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"A sincronização concede acesso aos seus contactos e ao histórico de chamadas quando tem uma ligação estabelecida."</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Não foi possível sincronizar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Não foi possível sincronizar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g> devido a PIN ou chave de acesso incorreto."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Não foi possível sincronizar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g> devido a PIN ou token de acesso incorreto."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Não é possível comunicar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Emparelhamento rejeitado por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Computador"</string>
@@ -349,7 +349,7 @@
<string name="debug_app" msgid="8903350241392391766">"Selecionar a aplicação a depurar"</string>
<string name="debug_app_not_set" msgid="1934083001283807188">"Nenhuma aplicação a depurar definida"</string>
<string name="debug_app_set" msgid="6599535090477753651">"A depurar aplicação: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="select_application" msgid="2543228890535466325">"Selecionar aplicação"</string>
+ <string name="select_application" msgid="2543228890535466325">"Selecionar app"</string>
<string name="no_application" msgid="9038334538870247690">"Nenhuma"</string>
<string name="wait_for_debugger" msgid="7461199843335409809">"Aguarde pelo depurador"</string>
<string name="wait_for_debugger_summary" msgid="6846330006113363286">"A aplicação depurada aguarda a anexação do depurador antes da execução"</string>
@@ -530,7 +530,7 @@
<string name="okay" msgid="949938843324579502">"OK"</string>
<string name="done" msgid="381184316122520313">"Concluir"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir a definição de alarmes e lembretes"</string>
+ <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permita que esta app defina alarmes e agende outras ações com base no tempo. Esta ação permite que a app seja executada em segundo plano, o que pode utilizar mais bateria.\n\nSe esta autorização estiver desativada, os alarmes existentes e os eventos com base no tempo agendados por esta app não funcionam."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"agendar, alarme, lembrete, relógio"</string>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index 658b15307f47..5cbca900c8bb 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Pequeno"</item>
+ <item msgid="1484561228522634915">"Padrão"</item>
+ <item msgid="4014311587094503943">"Grande"</item>
+ <item msgid="2904569270831156685">"Maior"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 816108e52bcf..da7dcc5fa268 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -532,7 +532,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index b839c12a3825..743fae201a1b 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Mic"</item>
+ <item msgid="1484561228522634915">"Prestabilit"</item>
+ <item msgid="4014311587094503943">"Mare"</item>
+ <item msgid="2904569270831156685">"Cel mai mare"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index ea5faa8dee93..fabfcdec3ae9 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -532,7 +532,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarme și mementouri"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permite setarea pentru alarme și mementouri"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarme și mementouri"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să stabilească alarme și să planifice acțiuni dependente de timp. Astfel, aplicația poate să ruleze în fundal, fapt care ar putea consuma mai multă baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să seteze alarme și să planifice acțiuni care trebuie realizate în timp scurt. Astfel, aplicația poate să ruleze în fundal, ceea ce ar putea crește consumul de baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programare, alarmă, memento, ceas"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activează"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activează Nu deranja"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 707a34a27d50..53194f6bb551 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Мелкий"</item>
+ <item msgid="1484561228522634915">"По умолчанию"</item>
+ <item msgid="4014311587094503943">"Крупный"</item>
+ <item msgid="2904569270831156685">"Самый крупный"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 9e4f23cc5a56..fe49f87d1f15 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -532,7 +532,7 @@
<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>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Если вы разрешите этому приложению устанавливать будильники и планировать на определенное время действия, оно будет работать в фоновом режиме. В таком случае заряд батареи может расходоваться быстрее.\n\nЕсли отключить эту настройку, текущие будильники и созданные приложением мероприятия перестанут запускаться."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Вы можете разрешить этому приложению устанавливать будильники и планировать запуск действий в определенное время. В этом случае оно будет работать в фоновом режиме и быстрее расходовать заряд батареи.\n\nЕсли отключить это разрешение, текущие будильники и созданные приложением события перестанут запускаться."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"установить, будильник, напоминание, часы"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Включить"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Включите режим \"Не беспокоить\""</string>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index 7a8e9ee8e3da..62b0e4c69c11 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"කුඩා"</item>
+ <item msgid="1484561228522634915">"පෙරනිමි"</item>
+ <item msgid="4014311587094503943">"විශාල"</item>
+ <item msgid="2904569270831156685">"විශාලතම"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index 5ff15e7c1e1f..6c76469e4c44 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Malé"</item>
+ <item msgid="1484561228522634915">"Predvolené"</item>
+ <item msgid="4014311587094503943">"Veľké"</item>
+ <item msgid="2904569270831156685">"Najväčšie"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 1d187039f369..3f6a44019b71 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -532,7 +532,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Budíky a pripomenutia"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Povoliť nastavovanie budíkov a pripomenutí"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a pripomenutia"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, súčasné budíky a udalosti s časovým obmedzením naplánované touto aplikáciu nebudú fungovať."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, existujúce budíky a udalosti s časovým obmedzením naplánované touto aplikáciu nebudú fungovať."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plán, budík, pripomenutie, hodiny"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Zapnúť"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zapnite režim bez vyrušení"</string>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index f1e59e725cf5..ea96c2fc6b2b 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Majhna"</item>
+ <item msgid="1484561228522634915">"Privzeta"</item>
+ <item msgid="4014311587094503943">"Velika"</item>
+ <item msgid="2904569270831156685">"Največja"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index 7bceea714e82..e818fb5840db 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"I vogël"</item>
+ <item msgid="1484561228522634915">"Parazgjedhja"</item>
+ <item msgid="4014311587094503943">"I madh"</item>
+ <item msgid="2904569270831156685">"Më i madhi"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index 36882c2fe2aa..b0506a10a4fe 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Мало"</item>
+ <item msgid="1484561228522634915">"Подразумевано"</item>
+ <item msgid="4014311587094503943">"Велико"</item>
+ <item msgid="2904569270831156685">"Највеће"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index 8061e9cb6237..5d1fa21c4e62 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Liten"</item>
+ <item msgid="1484561228522634915">"Standard"</item>
+ <item msgid="4014311587094503943">"Stor"</item>
+ <item msgid="2904569270831156685">"Störst"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index 862fe38f468d..49e3a24e97d2 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Ndogo"</item>
+ <item msgid="1484561228522634915">"Chaguomsingi"</item>
+ <item msgid="4014311587094503943">"Kubwa"</item>
+ <item msgid="2904569270831156685">"Kubwa zaidi"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 2f18e0765276..aa80661090ba 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"சிறியது"</item>
+ <item msgid="1484561228522634915">"இயல்பு"</item>
+ <item msgid="4014311587094503943">"பெரியது"</item>
+ <item msgid="2904569270831156685">"மிகப் பெரியது"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index ed5a6a6537b2..0fceab525e8d 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"చిన్నది"</item>
+ <item msgid="1484561228522634915">"ఆటోమేటిక్ సెట్టింగ్"</item>
+ <item msgid="4014311587094503943">"పెద్దది"</item>
+ <item msgid="2904569270831156685">"అతి పెద్దది"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index e0046fc074e1..8c23e6b72b7b 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"เล็ก"</item>
+ <item msgid="1484561228522634915">"ค่าเริ่มต้น"</item>
+ <item msgid="4014311587094503943">"ใหญ่"</item>
+ <item msgid="2904569270831156685">"ใหญ่ที่สุด"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 622587d7f83f..2b5f59519625 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Maliit"</item>
+ <item msgid="1484561228522634915">"Default"</item>
+ <item msgid="4014311587094503943">"Malaki"</item>
+ <item msgid="2904569270831156685">"Pinakamalaki"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 99dca9e027fc..8ce7fa790698 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Küçük"</item>
+ <item msgid="1484561228522634915">"Varsayılan"</item>
+ <item msgid="4014311587094503943">"Büyük"</item>
+ <item msgid="2904569270831156685">"En büyük"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 738e97e6d659..61229297036e 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -530,7 +530,7 @@
<string name="okay" msgid="949938843324579502">"Tamam"</string>
<string name="done" msgid="381184316122520313">"Bitti"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmlar ve hatırlatıcılar"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlanmasına izin ver"</string>
+ <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlamasına izin ver"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmlar ve hatırlatıcılar"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu uygulamanın alarm kurmasına ve zamana bağlı işlemler programlamasına izin verin. Bu izin, uygulamanın arka planda çalışmasına olanak sağlayarak daha fazla pil harcanmasına neden olabilir.\n\nBu izin verilmezse bu uygulama tarafından programlanmış mevcut alarmlar ve zamana bağlı etkinlikler çalışmaz."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"program, alarm, hatırlatıcı, saat"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index 976a48757a32..9fc3536dc9d8 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Малий"</item>
+ <item msgid="1484561228522634915">"За умовчанням"</item>
+ <item msgid="4014311587094503943">"Великий"</item>
+ <item msgid="2904569270831156685">"Найбільший"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 39b7394b8ff3..c837c3c86f93 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"چھوٹا"</item>
+ <item msgid="1484561228522634915">"ڈیفالٹ"</item>
+ <item msgid="4014311587094503943">"بڑا"</item>
+ <item msgid="2904569270831156685">"سب سے بڑا"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 7605bdcb094b..27259f7894ec 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Kichik"</item>
+ <item msgid="1484561228522634915">"Birlamchi"</item>
+ <item msgid="4014311587094503943">"Yirik"</item>
+ <item msgid="2904569270831156685">"Eng katta"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index 5306574d6406..22065ea4ab5b 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Nhỏ"</item>
+ <item msgid="1484561228522634915">"Mặc định"</item>
+ <item msgid="4014311587094503943">"Lớn"</item>
+ <item msgid="2904569270831156685">"Lớn nhất"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index ff3bac668bd6..c1fcda2df28a 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"小"</item>
+ <item msgid="1484561228522634915">"默认"</item>
+ <item msgid="4014311587094503943">"大"</item>
+ <item msgid="2904569270831156685">"最大"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index baf6662b2f93..932011cde975 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"小"</item>
+ <item msgid="1484561228522634915">"預設"</item>
+ <item msgid="4014311587094503943">"大"</item>
+ <item msgid="2904569270831156685">"最大"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index 1669e806a341..e8c530d208db 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"小"</item>
+ <item msgid="1484561228522634915">"預設"</item>
+ <item msgid="4014311587094503943">"大"</item>
+ <item msgid="2904569270831156685">"最大"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 50d292192727..4931c90915e4 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -240,7 +240,7 @@
<string name="adb_wireless_error" msgid="721958772149779856">"錯誤"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"無線偵錯"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"如要查看並使用可用的裝置,請開啟無線偵錯功能"</string>
- <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR 圖碼配對裝置"</string>
+ <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR code 配對裝置"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"使用 QR code 掃描器配對新裝置"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"使用配對碼配對裝置"</string>
<string name="adb_pair_method_code_summary" msgid="6370414511333685185">"使用六位數的配對碼配對新裝置"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index d62e519c2225..bcc0da08c5da 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -273,12 +273,10 @@
</string-array>
<string-array name="avatar_image_descriptions">
</string-array>
- <!-- no translation found for entries_font_size:0 (9181293769180886675) -->
- <!-- no translation found for entries_font_size:0 (6490061470416867723) -->
- <!-- no translation found for entries_font_size:1 (1484561228522634915) -->
- <!-- no translation found for entries_font_size:1 (3579015730662088893) -->
- <!-- no translation found for entries_font_size:2 (4014311587094503943) -->
- <!-- no translation found for entries_font_size:2 (1678068858001018666) -->
- <!-- no translation found for entries_font_size:3 (2904569270831156685) -->
- <!-- no translation found for entries_font_size:3 (490158884605093126) -->
+ <string-array name="entries_font_size">
+ <item msgid="9181293769180886675">"Esincane"</item>
+ <item msgid="1484561228522634915">"Okuzenzakalelayo"</item>
+ <item msgid="4014311587094503943">"kobukhulu"</item>
+ <item msgid="2904569270831156685">"Obukhulukazi"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index 2614644feb20..688fc720d058 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -55,6 +55,7 @@ public class DreamBackend {
public ComponentName settingsComponentName;
public CharSequence description;
public Drawable previewImage;
+ public boolean supportsComplications = false;
@Override
public String toString() {
@@ -175,6 +176,7 @@ public class DreamBackend {
if (dreamMetadata != null) {
dreamInfo.settingsComponentName = dreamMetadata.settingsActivity;
dreamInfo.previewImage = dreamMetadata.previewImage;
+ dreamInfo.supportsComplications = dreamMetadata.showComplications;
}
dreamInfos.add(dreamInfo);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index 6a1cee3146a2..562d20d05429 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -224,6 +224,9 @@ public class EnableZenModeDialog {
mMetricsLogger.logOnConditionSelected();
updateAlarmWarningText(tag.condition);
}
+ tag.line1.setStateDescription(
+ isChecked ? buttonView.getContext().getString(
+ com.android.internal.R.string.selected) : null);
}
});
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
index 87e97b17b914..abbdaa73c18e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
@@ -196,6 +196,9 @@ public class ZenDurationDialog {
if (isChecked) {
tag.rb.setChecked(true);
}
+ tag.line1.setStateDescription(
+ isChecked ? buttonView.getContext().getString(
+ com.android.internal.R.string.selected) : null);
}
});
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
index 81006dd6b011..0fa15eb6bc0c 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
@@ -33,7 +33,10 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager.SettableDeviceState;
+import com.google.common.truth.Expect;
+
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -45,6 +48,8 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
public class DeviceStateRotationLockSettingsManagerTest {
+ @Rule public Expect mExpect = Expect.create();
+
@Mock private Context mMockContext;
@Mock private Resources mMockResources;
@@ -117,4 +122,40 @@ public class DeviceStateRotationLockSettingsManagerTest {
new SettableDeviceState(/* deviceState= */ 0, /* isSettable= */ false)
).inOrder();
}
+
+ @Test
+ public void persistedInvalidIgnoredState_returnsDefaults() {
+ when(mMockResources.getStringArray(
+ R.array.config_perDeviceStateRotationLockDefaults)).thenReturn(
+ new String[]{"0:1", "1:0:2", "2:2"});
+ // Here 2 has IGNORED, and in the defaults 1 has IGNORED.
+ persistSettings("0:2:2:0:1:2");
+ DeviceStateRotationLockSettingsManager manager =
+ new DeviceStateRotationLockSettingsManager(mMockContext, mFakeSecureSettings);
+
+ mExpect.that(manager.getRotationLockSetting(0)).isEqualTo(1);
+ mExpect.that(manager.getRotationLockSetting(1)).isEqualTo(2);
+ mExpect.that(manager.getRotationLockSetting(2)).isEqualTo(2);
+ }
+
+ @Test
+ public void persistedValidValues_returnsPersistedValues() {
+ when(mMockResources.getStringArray(
+ R.array.config_perDeviceStateRotationLockDefaults)).thenReturn(
+ new String[]{"0:1", "1:0:2", "2:2"});
+ persistSettings("0:2:1:0:2:1");
+ DeviceStateRotationLockSettingsManager manager =
+ new DeviceStateRotationLockSettingsManager(mMockContext, mFakeSecureSettings);
+
+ mExpect.that(manager.getRotationLockSetting(0)).isEqualTo(2);
+ mExpect.that(manager.getRotationLockSetting(1)).isEqualTo(1);
+ mExpect.that(manager.getRotationLockSetting(2)).isEqualTo(1);
+ }
+
+ private void persistSettings(String value) {
+ mFakeSecureSettings.putStringForUser(
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+ value,
+ UserHandle.USER_CURRENT);
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
index 59d56747ec5d..6b81c1a6f794 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
@@ -16,6 +16,8 @@
package com.android.settingslib.notification;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -78,6 +80,8 @@ public class EnableZenModeDialogTest {
mController.mForeverId = Condition.newId(mContext).appendPath("forever").build();
when(mContext.getString(com.android.internal.R.string.zen_mode_forever))
.thenReturn("testSummary");
+ when(mContext.getString(com.android.internal.R.string.selected))
+ .thenReturn("selected");
NotificationManager.Policy alarmsEnabledPolicy = new NotificationManager.Policy(
NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0, 0);
doReturn(alarmsEnabledPolicy).when(mNotificationManager).getNotificationPolicy();
@@ -190,4 +194,25 @@ public class EnableZenModeDialogTest {
// alarm warning should NOT be null
assertNotNull(mController.computeAlarmWarningText(null));
}
+
+ @Test
+ public void testAccessibility() {
+ mController.bindConditions(null);
+ EnableZenModeDialog.ConditionTag forever = mController.getConditionTagAt(
+ ZenDurationDialog.FOREVER_CONDITION_INDEX);
+ EnableZenModeDialog.ConditionTag countdown = mController.getConditionTagAt(
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ EnableZenModeDialog.ConditionTag alwaysAsk = mController.getConditionTagAt(
+ ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX);
+
+ forever.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription().toString()).isEqualTo("selected");
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription()).isNull();
+
+ alwaysAsk.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription()).isNull();
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription().toString()).isEqualTo("selected");
+ }
} \ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
index 437c0d4f4469..fc45e89a6dd5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
@@ -16,6 +16,8 @@
package com.android.settingslib.notification;
+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.assertTrue;
@@ -205,4 +207,27 @@ public class ZenDurationDialogTest {
ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
assertEquals(120, tag.countdownZenDuration);
}
+
+ @Test
+ public void testAccessibility() {
+ Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
+ Settings.Secure.ZEN_DURATION_FOREVER);
+ mController.setupDialog(mBuilder);
+ ZenDurationDialog.ConditionTag forever = mController.getConditionTagAt(
+ ZenDurationDialog.FOREVER_CONDITION_INDEX);
+ ZenDurationDialog.ConditionTag countdown = mController.getConditionTagAt(
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ ZenDurationDialog.ConditionTag alwaysAsk = mController.getConditionTagAt(
+ ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX);
+
+ forever.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription().toString()).isEqualTo("selected");
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription()).isNull();
+
+ alwaysAsk.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription()).isNull();
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription().toString()).isEqualTo("selected");
+ }
} \ No newline at end of file
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index b5eaa4b776b8..6a07dc6603ca 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -221,6 +221,7 @@ public class SecureSettings {
Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO,
Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE,
Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME,
- Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED
+ Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED,
+ Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 534e31ae42ee..dd9b48457333 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -355,5 +355,6 @@ public class SecureSettingsValidators {
VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_CODE, ANY_STRING_VALIDATOR);
VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME, ANY_STRING_VALIDATOR);
VALIDATORS.put(Secure.LOCK_SCREEN_WEATHER_ENABLED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED, BOOLEAN_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index a78faaf90c37..c90b95a7fe62 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1822,6 +1822,9 @@ class SettingsProtoDumpUtil {
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED,
SecureSettingsProto.Accessibility
.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED,
+ SecureSettingsProto.Accessibility.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED);
p.end(accessibilityToken);
final long adaptiveSleepToken = p.start(SecureSettingsProto.ADAPTIVE_SLEEP);
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index 60bfdb2ee379..6474e6a867ac 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -43,6 +43,9 @@
},
{
"exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.Postsubmit"
}
]
},
@@ -160,5 +163,21 @@
}
]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "SystemUIGoogleScreenshotTests",
+ "options": [
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "include-annotation": "android.platform.test.annotations.Postsubmit"
+ }
+ ]
+ }
]
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index 17a94b8639d0..296c2ae5cf99 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -419,7 +419,7 @@ class ActivityLaunchAnimator(
internal val delegate: AnimationDelegate
init {
- delegate = AnimationDelegate(controller, callback, launchAnimator, listener)
+ delegate = AnimationDelegate(controller, callback, listener, launchAnimator)
}
@BinderThread
@@ -446,10 +446,10 @@ class ActivityLaunchAnimator(
constructor(
private val controller: Controller,
private val callback: Callback,
- /** The animator to use to animate the window launch. */
- private val launchAnimator: LaunchAnimator = DEFAULT_LAUNCH_ANIMATOR,
/** Listener for animation lifecycle events. */
- private val listener: Listener? = null
+ private val listener: Listener? = null,
+ /** The animator to use to animate the window launch. */
+ private val launchAnimator: LaunchAnimator = DEFAULT_LAUNCH_ANIMATOR
) : RemoteAnimationDelegate<IRemoteAnimationFinishedCallback> {
private val launchContainer = controller.launchContainer
private val context = launchContainer.context
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
index 40a5e9794d37..c49a487c6766 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
@@ -26,7 +26,7 @@ interface Expandable {
* currently not attached or visible).
*
* @param cujType the CUJ type from the [com.android.internal.jank.InteractionJankMonitor]
- * associated to the launch that will use this controller.
+ * associated to the launch that will use this controller.
*/
fun activityLaunchController(cujType: Int? = null): ActivityLaunchAnimator.Controller?
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 290328894439..f0a82113c3a3 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
@@ -19,14 +19,15 @@ package com.android.systemui.animation
import android.graphics.fonts.Font
import android.graphics.fonts.FontVariationAxis
import android.util.MathUtils
+import android.util.MathUtils.abs
+import java.lang.Float.max
+import java.lang.Float.min
private const val TAG_WGHT = "wght"
private const val TAG_ITAL = "ital"
-private const val FONT_WEIGHT_MAX = 1000f
-private const val FONT_WEIGHT_MIN = 0f
-private const val FONT_WEIGHT_ANIMATION_STEP = 10f
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
@@ -118,14 +119,17 @@ class FontInterpolator {
lerp(startAxes, endAxes) { tag, startValue, endValue ->
when (tag) {
// TODO: Good to parse 'fvar' table for retrieving default value.
- TAG_WGHT ->
- adjustWeight(
+ TAG_WGHT -> {
+ adaptiveAdjustWeight(
MathUtils.lerp(
startValue ?: FONT_WEIGHT_DEFAULT_VALUE,
endValue ?: FONT_WEIGHT_DEFAULT_VALUE,
progress
- )
+ ),
+ startValue ?: FONT_WEIGHT_DEFAULT_VALUE,
+ endValue ?: FONT_WEIGHT_DEFAULT_VALUE,
)
+ }
TAG_ITAL ->
adjustItalic(
MathUtils.lerp(
@@ -205,10 +209,14 @@ class FontInterpolator {
return result
}
- // For the performance reasons, we animate weight with FONT_WEIGHT_ANIMATION_STEP. This helps
+ // For the performance reasons, we animate weight with adaptive step. This helps
// Cache hit ratio in the Skia glyph cache.
- private fun adjustWeight(value: Float) =
- coerceInWithStep(value, FONT_WEIGHT_MIN, FONT_WEIGHT_MAX, FONT_WEIGHT_ANIMATION_STEP)
+ // 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.
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
index 9668066be125..3417ffd6b83a 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
@@ -75,7 +75,7 @@ class LaunchAnimator(private val timings: Timings, private val interpolators: In
* - Get the associated [Context].
* - Compute whether we are expanding fully above the launch container.
* - Get to overlay to which we initially put the window background layer, until the opening
- * window is made visible (see [openingWindowSyncView]).
+ * window is made visible (see [openingWindowSyncView]).
*
* This container can be changed to force this [Controller] to animate the expanding view
* inside a different location, for instance to ensure correct layering during the
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
index 774255be4007..ed8e70568b48 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -24,7 +24,7 @@ interface LaunchableView {
* Set whether this view should block/postpone all calls to [View.setVisibility]. This ensures
* that this view:
* - remains invisible during the launch animation given that it is ghosted and already drawn
- * somewhere else.
+ * somewhere else.
* - remains invisible as long as a dialog expanded from it is shown.
* - restores its expected visibility once the dialog expanded from it is dismissed.
*
@@ -35,8 +35,7 @@ interface LaunchableView {
*
* Note that calls to [View.setTransitionVisibility] shouldn't be blocked.
*
- * @param block whether we should block/postpone all calls to `setVisibility` and
- * `setTransitionVisibility`.
+ * @param block whether we should block/postpone all calls to `setVisibility`.
*/
fun setShouldBlockVisibilityChanges(block: Boolean)
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
index 0e2d23b04a4f..6946e6bf88a8 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
@@ -182,9 +182,9 @@ class RemoteTransitionAdapter {
* Represents a TransitionInfo object as an array of old-style targets
*
* @param wallpapers If true, this will return wallpaper targets; otherwise it returns
- * non-wallpaper targets.
+ * non-wallpaper targets.
* @param leashMap Temporary map of change leash -> launcher leash. Is an output, so should
- * be populated by this function. If null, it is ignored.
+ * be populated by this function. If null, it is ignored.
*/
fun wrapTargets(
info: TransitionInfo,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
index a96f893a8db4..b89a8b0e0272 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
@@ -6,6 +6,7 @@ object ShadeInterpolation {
/**
* Interpolate alpha for notification background scrim during shade expansion.
+ *
* @param fraction Shade expansion fraction
*/
@JvmStatic
@@ -16,6 +17,7 @@ object ShadeInterpolation {
/**
* Interpolate alpha for shade content during shade expansion.
+ *
* @param fraction Shade expansion fraction
*/
@JvmStatic
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 a08b59829de2..7fe94d349c42 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
@@ -190,6 +190,7 @@ class TextAnimator(layout: Layout, private val invalidateCallback: () -> Unit) {
* @param textSize an optional font size.
* @param colors an optional colors array that must be the same size as numLines passed to
* the TextInterpolator
+ * @param strokeWidth an optional paint stroke width
* @param animate an optional boolean indicating true for showing style transition as animation,
* false for immediate style transition. True by default.
* @param duration an optional animation duration in milliseconds. This is ignored if animate is
@@ -201,6 +202,7 @@ class TextAnimator(layout: Layout, private val invalidateCallback: () -> Unit) {
weight: Int = -1,
textSize: Float = -1f,
color: Int? = null,
+ strokeWidth: Float = -1f,
animate: Boolean = true,
duration: Long = -1L,
interpolator: TimeInterpolator? = null,
@@ -254,6 +256,9 @@ class TextAnimator(layout: Layout, private val invalidateCallback: () -> Unit) {
if (color != null) {
textInterpolator.targetPaint.color = color
}
+ if (strokeWidth >= 0F) {
+ textInterpolator.targetPaint.strokeWidth = strokeWidth
+ }
textInterpolator.onTargetPaintModified()
if (animate) {
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 341784e26257..3eb7fd84dc49 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
@@ -161,7 +161,6 @@ class TextInterpolator(layout: Layout) {
* This API is useful to continue animation from the middle of the state. For example, if you
* animate weight from 200 to 400, then if you want to move back to 200 at the half of the
* animation, it will look like
- *
* <pre> <code>
* ```
* val interp = TextInterpolator(layout)
@@ -474,6 +473,7 @@ class TextInterpolator(layout: Layout) {
// TODO(172943390): Add other interpolation or support custom interpolator.
out.textSize = MathUtils.lerp(from.textSize, to.textSize, progress)
out.color = ColorUtils.blendARGB(from.color, to.color, progress)
+ out.strokeWidth = MathUtils.lerp(from.strokeWidth, to.strokeWidth, progress)
}
// Shape the text and stores the result to out argument.
@@ -497,7 +497,9 @@ class TextInterpolator(layout: Layout) {
count,
layout.textDirectionHeuristic,
paint
- ) { _, _, glyphs, _ -> runs.add(glyphs) }
+ ) { _, _, glyphs, _ ->
+ runs.add(glyphs)
+ }
out.add(runs)
if (lineNo > 0) {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
index a1d9d90523eb..e42b589f05cf 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
@@ -24,7 +24,7 @@ import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
/** An [ImageView] that also implements [LaunchableView]. */
-class LaunchableImageView : ImageView, LaunchableView {
+open class LaunchableImageView : ImageView, LaunchableView {
private val delegate =
LaunchableViewDelegate(
this,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
index 286996dcaeaa..147669528c5e 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
@@ -24,7 +24,7 @@ import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
/** A [TextView] that also implements [LaunchableView]. */
-class LaunchableTextView : TextView, LaunchableView {
+open class LaunchableTextView : TextView, LaunchableView {
private val delegate =
LaunchableViewDelegate(
this,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
index 442c6fadb7c1..bd91c65ecc6e 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
@@ -68,7 +68,7 @@ class RippleAnimation(private val config: RippleAnimationConfig) {
private fun applyConfigToShader() {
with(rippleShader) {
setCenter(config.centerX, config.centerY)
- setMaxSize(config.maxWidth, config.maxHeight)
+ rippleSize.setMaxSize(config.maxWidth, config.maxHeight)
pixelDensity = config.pixelDensity
color = ColorUtils.setAlphaComponent(config.color, config.opacity)
sparkleStrength = config.sparkleStrength
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
index 61ca90a297fe..5ed723bdd254 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
@@ -15,16 +15,16 @@
*/
package com.android.systemui.surfaceeffects.ripple
-import android.graphics.PointF
import android.graphics.RuntimeShader
+import android.util.Log
import android.util.MathUtils
+import androidx.annotation.VisibleForTesting
import com.android.systemui.animation.Interpolators
import com.android.systemui.surfaceeffects.shaderutil.SdfShaderLibrary
import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
/**
* Shader class that renders an expanding ripple effect. The ripple contains three elements:
- *
* 1. an expanding filled [RippleShape] that appears in the beginning and quickly fades away
* 2. an expanding ring that appears throughout the effect
* 3. an expanding ring-shaped area that reveals noise over #2.
@@ -44,6 +44,8 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
}
// language=AGSL
companion object {
+ private val TAG = RippleShader::class.simpleName
+
// Default fade in/ out values. The value range is [0,1].
const val DEFAULT_FADE_IN_START = 0f
const val DEFAULT_FADE_OUT_END = 1f
@@ -99,7 +101,7 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
vec4 main(vec2 p) {
float sparkleRing = soften(roundedBoxRing(p-in_center, in_size, in_cornerRadius,
in_thickness), in_blur);
- float inside = soften(sdRoundedBox(p-in_center, in_size * 1.2, in_cornerRadius),
+ float inside = soften(sdRoundedBox(p-in_center, in_size * 1.25, in_cornerRadius),
in_blur);
float sparkle = sparkles(p - mod(p, in_pixelDensity * 0.8), in_time * 0.00175)
* (1.-sparkleRing) * in_fadeSparkle;
@@ -184,12 +186,17 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
setFloatUniform("in_center", x, y)
}
- /** Max width of the ripple. */
- private var maxSize: PointF = PointF()
- fun setMaxSize(width: Float, height: Float) {
- maxSize.x = width
- maxSize.y = height
- }
+ /**
+ * Blur multipliers for the ripple.
+ *
+ * <p>It interpolates from [blurStart] to [blurEnd] based on the [progress]. Increase number to
+ * add more blur.
+ */
+ var blurStart: Float = 1.25f
+ var blurEnd: Float = 0.5f
+
+ /** Size of the ripple. */
+ val rippleSize = RippleSize()
/**
* Linear progress of the ripple. Float value between [0, 1].
@@ -209,15 +216,19 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
/** Progress with Standard easing curve applied. */
private var progress: Float = 0.0f
set(value) {
- currentWidth = maxSize.x * value
- currentHeight = maxSize.y * value
- setFloatUniform("in_size", currentWidth, currentHeight)
+ field = value
+
+ rippleSize.update(value)
- setFloatUniform("in_thickness", maxSize.y * value * 0.5f)
- // radius should not exceed width and height values.
- setFloatUniform("in_cornerRadius", Math.min(maxSize.x, maxSize.y) * value)
+ setFloatUniform("in_size", rippleSize.currentWidth, rippleSize.currentHeight)
+ setFloatUniform("in_thickness", rippleSize.currentHeight * 0.5f)
+ // Corner radius is always max of the min between the current width and height.
+ setFloatUniform(
+ "in_cornerRadius",
+ Math.min(rippleSize.currentWidth, rippleSize.currentHeight)
+ )
- setFloatUniform("in_blur", MathUtils.lerp(1.25f, 0.5f, value))
+ setFloatUniform("in_blur", MathUtils.lerp(blurStart, blurEnd, value))
}
/** Play time since the start of the effect. */
@@ -264,12 +275,6 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
setFloatUniform("in_pixelDensity", value)
}
- var currentWidth: Float = 0f
- private set
-
- var currentHeight: Float = 0f
- private set
-
/** Parameters that are used to fade in/ out of the sparkle ring. */
val sparkleRingFadeParams =
FadeParams(
@@ -305,6 +310,7 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
* Parameters used for fade in and outs of the ripple.
*
* <p>Note that all the fade in/ outs are "linear" progression.
+ *
* ```
* (opacity)
* 1
@@ -319,6 +325,7 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
* fadeIn fadeOut
* Start & End Start & End
* ```
+ *
* <p>If no fade in/ out is needed, set [fadeInStart] and [fadeInEnd] to 0; [fadeOutStart] and
* [fadeOutEnd] to 1.
*/
@@ -342,4 +349,102 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
/** The endpoint of the fade out, given that the animation goes from 0 to 1. */
var fadeOutEnd: Float = DEFAULT_FADE_OUT_END,
)
+
+ /**
+ * Desired size of the ripple at a point t in [progress].
+ *
+ * <p>Note that [progress] is curved and normalized. Below is an example usage:
+ * SizeAtProgress(t= 0f, width= 0f, height= 0f), SizeAtProgress(t= 0.2f, width= 500f, height=
+ * 700f), SizeAtProgress(t= 1f, width= 100f, height= 300f)
+ *
+ * <p>For simple ripple effects, you will want to use [setMaxSize] as it is translated into:
+ * SizeAtProgress(t= 0f, width= 0f, height= 0f), SizeAtProgress(t= 1f, width= maxWidth, height=
+ * maxHeight)
+ */
+ data class SizeAtProgress(
+ /** Time t in [0,1] progress range. */
+ var t: Float,
+ /** Target width size of the ripple at time [t]. */
+ var width: Float,
+ /** Target height size of the ripple at time [t]. */
+ var height: Float
+ )
+
+ /** Updates and stores the ripple size. */
+ inner class RippleSize {
+ @VisibleForTesting var sizes = mutableListOf<SizeAtProgress>()
+ @VisibleForTesting var currentSizeIndex = 0
+ @VisibleForTesting val initialSize = SizeAtProgress(0f, 0f, 0f)
+
+ var currentWidth: Float = 0f
+ private set
+ var currentHeight: Float = 0f
+ private set
+
+ /**
+ * Sets the max size of the ripple.
+ *
+ * <p>Use this if the ripple shape simply changes linearly.
+ */
+ fun setMaxSize(width: Float, height: Float) {
+ setSizeAtProgresses(initialSize, SizeAtProgress(1f, width, height))
+ }
+
+ /**
+ * Sets the list of [sizes].
+ *
+ * <p>Note that setting this clears the existing sizes.
+ */
+ fun setSizeAtProgresses(vararg sizes: SizeAtProgress) {
+ // Reset everything.
+ this.sizes.clear()
+ currentSizeIndex = 0
+
+ this.sizes.addAll(sizes)
+ this.sizes.sortBy { it.t }
+ }
+
+ /**
+ * Updates the current ripple size based on the progress.
+ *
+ * <p>Should be called when progress updates.
+ */
+ fun update(progress: Float) {
+ val targetIndex = updateTargetIndex(progress)
+ val prevIndex = Math.max(targetIndex - 1, 0)
+
+ val targetSize = sizes[targetIndex]
+ val prevSize = sizes[prevIndex]
+
+ val subProgress = subProgress(prevSize.t, targetSize.t, progress)
+
+ currentWidth = targetSize.width * subProgress + prevSize.width
+ currentHeight = targetSize.height * subProgress + prevSize.height
+ }
+
+ private fun updateTargetIndex(progress: Float): Int {
+ if (sizes.isEmpty()) {
+ // It could be empty on init.
+ if (progress > 0f) {
+ Log.e(
+ TAG,
+ "Did you forget to set the ripple size? Use [setMaxSize] or " +
+ "[setSizeAtProgresses] before playing the animation."
+ )
+ }
+ // If there's no size is set, we set everything to 0 and return early.
+ setSizeAtProgresses(initialSize)
+ return currentSizeIndex
+ }
+
+ var candidate = sizes[currentSizeIndex]
+
+ while (progress > candidate.t) {
+ currentSizeIndex = Math.min(currentSizeIndex + 1, sizes.size - 1)
+ candidate = sizes[currentSizeIndex]
+ }
+
+ return currentSizeIndex
+ }
+ }
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
index 3c9328c82b83..4c7c43548016 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
@@ -45,12 +45,8 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
var duration: Long = 1750
- private var maxWidth: Float = 0.0f
- private var maxHeight: Float = 0.0f
fun setMaxSize(maxWidth: Float, maxHeight: Float) {
- this.maxWidth = maxWidth
- this.maxHeight = maxHeight
- rippleShader.setMaxSize(maxWidth, maxHeight)
+ rippleShader.rippleSize.setMaxSize(maxWidth, maxHeight)
}
private var centerX: Float = 0.0f
@@ -84,6 +80,106 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
ripplePaint.shader = rippleShader
}
+ /**
+ * Sets the fade parameters for the base ring.
+ *
+ * <p>Base ring indicates a blurred ring below the sparkle ring. See
+ * [RippleShader.baseRingFadeParams].
+ */
+ @JvmOverloads
+ fun setBaseRingFadeParams(
+ fadeInStart: Float = rippleShader.baseRingFadeParams.fadeInStart,
+ fadeInEnd: Float = rippleShader.baseRingFadeParams.fadeInEnd,
+ fadeOutStart: Float = rippleShader.baseRingFadeParams.fadeOutStart,
+ fadeOutEnd: Float = rippleShader.baseRingFadeParams.fadeOutEnd
+ ) {
+ setFadeParams(
+ rippleShader.baseRingFadeParams,
+ fadeInStart,
+ fadeInEnd,
+ fadeOutStart,
+ fadeOutEnd
+ )
+ }
+
+ /**
+ * Sets the fade parameters for the sparkle ring.
+ *
+ * <p>Sparkle ring refers to the ring that's drawn on top of the base ring. See
+ * [RippleShader.sparkleRingFadeParams].
+ */
+ @JvmOverloads
+ fun setSparkleRingFadeParams(
+ fadeInStart: Float = rippleShader.sparkleRingFadeParams.fadeInStart,
+ fadeInEnd: Float = rippleShader.sparkleRingFadeParams.fadeInEnd,
+ fadeOutStart: Float = rippleShader.sparkleRingFadeParams.fadeOutStart,
+ fadeOutEnd: Float = rippleShader.sparkleRingFadeParams.fadeOutEnd
+ ) {
+ setFadeParams(
+ rippleShader.sparkleRingFadeParams,
+ fadeInStart,
+ fadeInEnd,
+ fadeOutStart,
+ fadeOutEnd
+ )
+ }
+
+ /**
+ * Sets the fade parameters for the center fill.
+ *
+ * <p>One common use case is set all the params to 1, which completely removes the center fill.
+ * See [RippleShader.centerFillFadeParams].
+ */
+ @JvmOverloads
+ fun setCenterFillFadeParams(
+ fadeInStart: Float = rippleShader.centerFillFadeParams.fadeInStart,
+ fadeInEnd: Float = rippleShader.centerFillFadeParams.fadeInEnd,
+ fadeOutStart: Float = rippleShader.centerFillFadeParams.fadeOutStart,
+ fadeOutEnd: Float = rippleShader.centerFillFadeParams.fadeOutEnd
+ ) {
+ setFadeParams(
+ rippleShader.centerFillFadeParams,
+ fadeInStart,
+ fadeInEnd,
+ fadeOutStart,
+ fadeOutEnd
+ )
+ }
+
+ private fun setFadeParams(
+ fadeParams: RippleShader.FadeParams,
+ fadeInStart: Float,
+ fadeInEnd: Float,
+ fadeOutStart: Float,
+ fadeOutEnd: Float
+ ) {
+ with(fadeParams) {
+ this.fadeInStart = fadeInStart
+ this.fadeInEnd = fadeInEnd
+ this.fadeOutStart = fadeOutStart
+ this.fadeOutEnd = fadeOutEnd
+ }
+ }
+
+ /**
+ * Sets blur multiplier at start and end of the progress.
+ *
+ * <p>It interpolates between [start] and [end]. No need to set it if using default blur.
+ */
+ fun setBlur(start: Float, end: Float) {
+ rippleShader.blurStart = start
+ rippleShader.blurEnd = end
+ }
+
+ /**
+ * Sets the list of [RippleShader.SizeAtProgress].
+ *
+ * <p>Note that this clears the list before it sets with the new data.
+ */
+ fun setSizeAtProgresses(vararg targetSizes: RippleShader.SizeAtProgress) {
+ rippleShader.rippleSize.setSizeAtProgresses(*targetSizes)
+ }
+
@JvmOverloads
fun startRipple(onAnimationEnd: Runnable? = null) {
if (animator.isRunning) {
@@ -133,13 +229,13 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
}
// To reduce overdraw, we mask the effect to a circle or a rectangle that's bigger than the
// active effect area. Values here should be kept in sync with the animation implementation
- // in the ripple shader. (Twice bigger)
+ // in the ripple shader.
if (rippleShape == RippleShape.CIRCLE) {
- val maskRadius = rippleShader.currentWidth
+ val maskRadius = rippleShader.rippleSize.currentWidth
canvas.drawCircle(centerX, centerY, maskRadius, ripplePaint)
- } else {
- val maskWidth = rippleShader.currentWidth * 2
- val maskHeight = rippleShader.currentHeight * 2
+ } else if (rippleShape == RippleShape.ELLIPSE) {
+ val maskWidth = rippleShader.rippleSize.currentWidth * 2
+ val maskHeight = rippleShader.rippleSize.currentHeight * 2
canvas.drawRect(
/* left= */ centerX - maskWidth,
/* top= */ centerY - maskHeight,
@@ -147,6 +243,10 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
/* bottom= */ centerY + maskHeight,
ripplePaint
)
+ } else { // RippleShape.RoundedBox
+ // No masking for the rounded box, as it has more blur which requires larger bounds.
+ // Masking creates sharp bounds even when the masking is 4 times bigger.
+ canvas.drawPaint(ripplePaint)
}
}
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
index 8b2f46648fef..78898932249b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
@@ -50,9 +50,9 @@ class SdfShaderLibrary {
float roundedBoxRing(vec2 p, vec2 size, float cornerRadius,
float borderThickness) {
- float outerRoundBox = sdRoundedBox(p, size, cornerRadius);
- float innerRoundBox = sdRoundedBox(p, size - vec2(borderThickness),
- cornerRadius - borderThickness);
+ float outerRoundBox = sdRoundedBox(p, size + vec2(borderThickness),
+ cornerRadius + borderThickness);
+ float innerRoundBox = sdRoundedBox(p, size, cornerRadius);
return subtract(outerRoundBox, innerRoundBox);
}
"""
@@ -69,10 +69,13 @@ class SdfShaderLibrary {
vec2 u = wh*p, v = wh*wh;
- float U1 = u.y/2.0; float U5 = 4.0*U1;
- float U2 = v.y-v.x; float U6 = 6.0*U1;
- float U3 = u.x-U2; float U7 = 3.0*U3;
+ float U1 = u.y/2.0;
+ float U2 = v.y-v.x;
+ float U3 = u.x-U2;
float U4 = u.x+U2;
+ float U5 = 4.0*U1;
+ float U6 = 6.0*U1;
+ float U7 = 3.0*U3;
float t = 0.5;
for (int i = 0; i < 3; i ++) {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
index 79bc2f432ded..89871fa7d875 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
@@ -30,12 +30,14 @@ data class TurbulenceNoiseAnimationConfig(
* Noise move speed variables.
*
* Its sign determines the direction; magnitude determines the speed. <ul>
+ *
* ```
* <li> [noiseMoveSpeedX] positive: right to left; negative: left to right.
* <li> [noiseMoveSpeedY] positive: bottom to top; negative: top to bottom.
* <li> [noiseMoveSpeedZ] its sign doesn't matter much, as it moves in Z direction. Use it
* to add turbulence in place.
* ```
+ *
* </ul>
*/
val noiseMoveSpeedX: Float = 0f,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt b/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt
new file mode 100644
index 000000000000..35dbb89ad801
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt
@@ -0,0 +1,80 @@
+/*
+ * 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.util
+
+import androidx.core.animation.Animator
+
+/**
+ * Add an action which will be invoked when the animation has ended.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.end
+ */
+inline fun Animator.doOnEnd(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onEnd = action)
+
+/**
+ * Add an action which will be invoked when the animation has started.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.start
+ */
+inline fun Animator.doOnStart(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onStart = action)
+
+/**
+ * Add an action which will be invoked when the animation has been cancelled.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.cancel
+ */
+inline fun Animator.doOnCancel(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onCancel = action)
+
+/**
+ * Add an action which will be invoked when the animation has repeated.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ */
+inline fun Animator.doOnRepeat(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onRepeat = action)
+
+/**
+ * Add a listener to this Animator using the provided actions.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ */
+inline fun Animator.addListener(
+ crossinline onEnd: (animator: Animator) -> Unit = {},
+ crossinline onStart: (animator: Animator) -> Unit = {},
+ crossinline onCancel: (animator: Animator) -> Unit = {},
+ crossinline onRepeat: (animator: Animator) -> Unit = {}
+): Animator.AnimatorListener {
+ val listener =
+ object : Animator.AnimatorListener {
+ override fun onAnimationRepeat(animator: Animator) = onRepeat(animator)
+ override fun onAnimationEnd(animator: Animator) = onEnd(animator)
+ override fun onAnimationCancel(animator: Animator) = onCancel(animator)
+ override fun onAnimationStart(animator: Animator) = onStart(animator)
+ }
+ addListener(listener)
+ return listener
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt
new file mode 100644
index 000000000000..459a38e9318c
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt
@@ -0,0 +1,94 @@
+/*
+ * 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.internal.systemui.lint
+
+import com.android.tools.lint.client.api.UElementHandler
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import java.util.regex.Pattern
+import org.jetbrains.uast.UAnnotation
+import org.jetbrains.uast.UElement
+
+class DemotingTestWithoutBugDetector : Detector(), SourceCodeScanner {
+ override fun getApplicableUastTypes(): List<Class<out UElement>> {
+ return listOf(UAnnotation::class.java)
+ }
+
+ override fun createUastHandler(context: JavaContext): UElementHandler {
+ return object : UElementHandler() {
+ override fun visitAnnotation(node: UAnnotation) {
+ // Annotations having int bugId field
+ if (node.qualifiedName in DEMOTING_ANNOTATION_BUG_ID) {
+ val bugId = node.findAttributeValue("bugId")!!.evaluate() as Int
+ if (bugId <= 0) {
+ val location = context.getLocation(node)
+ val message = "Please attach a bug id to track demoted test"
+ context.report(ISSUE, node, location, message)
+ }
+ }
+ // @Ignore has a String field for reason
+ if (node.qualifiedName == DEMOTING_ANNOTATION_IGNORE) {
+ val reason = node.findAttributeValue("value")!!.evaluate() as String
+ val bugPattern = Pattern.compile("b/\\d+")
+ if (!bugPattern.matcher(reason).find()) {
+ val location = context.getLocation(node)
+ val message = "Please attach a bug (e.g. b/123) to track demoted test"
+ context.report(ISSUE, node, location, message)
+ }
+ }
+ }
+ }
+ }
+
+ companion object {
+ val DEMOTING_ANNOTATION_BUG_ID =
+ listOf(
+ "androidx.test.filters.FlakyTest",
+ "android.platform.test.annotations.FlakyTest",
+ "android.platform.test.rule.PlatinumRule.Platinum",
+ )
+
+ const val DEMOTING_ANNOTATION_IGNORE = "org.junit.Ignore"
+
+ @JvmField
+ val ISSUE: Issue =
+ Issue.create(
+ id = "DemotingTestWithoutBug",
+ briefDescription = "Demoting a test without attaching a bug.",
+ explanation =
+ """
+ Annotations (`@FlakyTest`) demote tests to an unmonitored \
+ test suite. Please set the `bugId` field in such annotations to track \
+ the test status.
+ """,
+ category = Category.TESTING,
+ priority = 8,
+ severity = Severity.WARNING,
+ implementation =
+ Implementation(
+ DemotingTestWithoutBugDetector::class.java,
+ Scope.JAVA_FILE_SCOPE
+ )
+ )
+ }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
new file mode 100644
index 000000000000..30e2a2527a93
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
@@ -0,0 +1,127 @@
+/*
+ * 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.internal.systemui.lint
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Context
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Location
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UClass
+
+/**
+ * Checks if any class has implemented the `Dumpable` interface but has not registered itself with
+ * the `DumpManager`.
+ */
+@Suppress("UnstableApiUsage")
+class DumpableNotRegisteredDetector : Detector(), SourceCodeScanner {
+
+ private var isDumpable: Boolean = false
+ private var isCoreStartable: Boolean = false
+ private var hasRegisterCall: Boolean = false
+ private var classLocation: Location? = null
+
+ override fun beforeCheckFile(context: Context) {
+ isDumpable = false
+ isCoreStartable = false
+ hasRegisterCall = false
+ classLocation = null
+ }
+
+ override fun applicableSuperClasses(): List<String> {
+ return listOf(DUMPABLE_CLASS_NAME)
+ }
+
+ override fun getApplicableMethodNames(): List<String> {
+ return listOf("registerDumpable", "registerNormalDumpable", "registerCriticalDumpable")
+ }
+
+ override fun visitClass(context: JavaContext, declaration: UClass) {
+ if (declaration.isInterface || context.evaluator.isAbstract(declaration)) {
+ // Don't require interfaces or abstract classes to call `register` (assume the full
+ // implementations will call it). This also means that we correctly don't warn for the
+ // `Dumpable` interface itself.
+ return
+ }
+
+ classLocation = context.getNameLocation(declaration)
+
+ val superTypeClassNames = declaration.superTypes.mapNotNull { it.resolve()?.qualifiedName }
+ isDumpable = superTypeClassNames.contains(DUMPABLE_CLASS_NAME)
+ isCoreStartable = superTypeClassNames.contains(CORE_STARTABLE_CLASS_NAME)
+ }
+
+ override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+ if (context.evaluator.isMemberInSubClassOf(method, DUMP_MANAGER_CLASS_NAME)) {
+ hasRegisterCall = true
+ }
+ }
+
+ override fun afterCheckFile(context: Context) {
+ if (!isDumpable) {
+ return
+ }
+ if (isDumpable && isCoreStartable) {
+ // CoreStartables will be automatically registered, so classes that implement
+ // CoreStartable do not need a `register` call.
+ return
+ }
+
+ if (!hasRegisterCall) {
+ context.report(
+ issue = ISSUE,
+ location = classLocation!!,
+ message =
+ "Any class implementing `Dumpable` must call " +
+ "`DumpManager.registerNormalDumpable` or " +
+ "`DumpManager.registerCriticalDumpable`",
+ )
+ }
+ }
+
+ companion object {
+ @JvmField
+ val ISSUE: Issue =
+ Issue.create(
+ id = "DumpableNotRegistered",
+ briefDescription = "Dumpable not registered with DumpManager.",
+ explanation =
+ """
+ This class has implemented the `Dumpable` interface, but it has not registered \
+ itself with the `DumpManager`. This means that the class will never actually \
+ be dumped. Please call `DumpManager.registerNormalDumpable` or \
+ `DumpManager.registerCriticalDumpable` in the class's constructor or \
+ initialization method.""",
+ category = Category.CORRECTNESS,
+ priority = 8,
+ severity = Severity.WARNING,
+ implementation =
+ Implementation(DumpableNotRegisteredDetector::class.java, Scope.JAVA_FILE_SCOPE)
+ )
+
+ private const val DUMPABLE_CLASS_NAME = "com.android.systemui.Dumpable"
+ private const val CORE_STARTABLE_CLASS_NAME = "com.android.systemui.CoreStartable"
+ private const val DUMP_MANAGER_CLASS_NAME = "com.android.systemui.dump.DumpManager"
+ }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
index 254a6fb4714f..387b67d231cd 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
@@ -32,13 +32,15 @@ class SystemUIIssueRegistry : IssueRegistry() {
BindServiceOnMainThreadDetector.ISSUE,
BroadcastSentViaContextDetector.ISSUE,
CleanArchitectureDependencyViolationDetector.ISSUE,
+ DumpableNotRegisteredDetector.ISSUE,
SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY,
SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY,
NonInjectedMainThreadDetector.ISSUE,
RegisterReceiverViaContextDetector.ISSUE,
SoftwareBitmapDetector.ISSUE,
NonInjectedServiceDetector.ISSUE,
- StaticSettingsProviderDetector.ISSUE
+ StaticSettingsProviderDetector.ISSUE,
+ DemotingTestWithoutBugDetector.ISSUE
)
override val api: Int
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
index a4b59fd8e086..a5f832a17de4 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
@@ -64,7 +64,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
class BadClass(
private val viewModel: ViewModel,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -98,7 +99,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
class BadClass(
private val repository: Repository,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -136,7 +138,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
private val interactor: Interactor,
private val viewmodel: ViewModel,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -176,7 +179,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
class BadClass(
private val interactor: Interactor,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -207,7 +211,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
data class Model(
private val name: String,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
private val REPOSITORY_FILE =
TestFiles.kotlin(
@@ -228,7 +233,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
return models
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val INTERACTOR_FILE =
TestFiles.kotlin(
@@ -245,7 +251,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
return repository.getModels()
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val VIEW_MODEL_FILE =
TestFiles.kotlin(
@@ -262,7 +269,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
return interactor.getModels().map { model -> model.name }
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val NON_CLEAN_ARCHITECTURE_FILE =
TestFiles.kotlin(
@@ -282,7 +290,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
)
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val LEGITIMATE_FILES =
arrayOf(
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt
new file mode 100644
index 000000000000..63eb2632979c
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt
@@ -0,0 +1,313 @@
+/*
+ * 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.internal.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+class DemotingTestWithoutBugDetectorTest : SystemUILintDetectorTest() {
+
+ override fun getDetector(): Detector = DemotingTestWithoutBugDetector()
+ override fun getIssues(): List<Issue> = listOf(DemotingTestWithoutBugDetector.ISSUE)
+
+ @Test
+ fun testMarkFlaky_withBugId() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+ import androidx.test.filters.FlakyTest;
+
+ @FlakyTest(bugId = 123)
+ public class TestClass {
+ public void testCase() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(DemotingTestWithoutBugDetector.ISSUE)
+ .run()
+ .expectClean()
+
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+ import android.platform.test.annotations.FlakyTest;
+
+ @FlakyTest(bugId = 123)
+ public class TestClass {
+ public void testCase() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(DemotingTestWithoutBugDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun testMarkFlaky_withoutBugId() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+ import androidx.test.filters.FlakyTest;
+
+ @FlakyTest
+ public class TestClass {
+ public void testCase() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(DemotingTestWithoutBugDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test [DemotingTestWithoutBug]
+ @FlakyTest
+ ~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+ import android.platform.test.annotations.FlakyTest;
+
+ @FlakyTest
+ public class TestClass {
+ public void testCase() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(DemotingTestWithoutBugDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test [DemotingTestWithoutBug]
+ @FlakyTest
+ ~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
+ fun testExcludeDevices_withBugId() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+ import android.platform.test.rule.PlatinumRule.Platinum;
+
+ @Platinum(devices = "foo,bar", bugId = 123)
+ public class TestClass {
+ public void testCase() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(DemotingTestWithoutBugDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun testExcludeDevices_withoutBugId() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+ import android.platform.test.rule.PlatinumRule.Platinum;
+
+ @Platinum(devices = "foo,bar")
+ public class TestClass {
+ public void testCase() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(DemotingTestWithoutBugDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test [DemotingTestWithoutBug]
+ @Platinum(devices = "foo,bar")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
+ fun testIgnore_withBug() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+ import org.junit.Ignore;
+
+ @Ignore("Blocked by b/123.")
+ public class TestClass {
+ public void testCase() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(DemotingTestWithoutBugDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun testIgnore_withoutBug() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+ import org.junit.Ignore;
+
+ @Ignore
+ public class TestClass {
+ public void testCase() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(DemotingTestWithoutBugDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/test/pkg/TestClass.java:4: Warning: Please attach a bug (e.g. b/123) to track demoted test [DemotingTestWithoutBug]
+ @Ignore
+ ~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+ import org.junit.Ignore;
+
+ @Ignore("Not ready")
+ public class TestClass {
+ public void testCase() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(DemotingTestWithoutBugDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/test/pkg/TestClass.java:4: Warning: Please attach a bug (e.g. b/123) to track demoted test [DemotingTestWithoutBug]
+ @Ignore("Not ready")
+ ~~~~~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ }
+
+ private val filtersFlakyTestStub: TestFile =
+ java(
+ """
+ package androidx.test.filters;
+
+ public @interface FlakyTest {
+ int bugId() default -1;
+ }
+ """
+ )
+ private val annotationsFlakyTestStub: TestFile =
+ java(
+ """
+ package android.platform.test.annotations;
+
+ public @interface FlakyTest {
+ int bugId() default -1;
+ }
+ """
+ )
+ private val annotationsPlatinumStub: TestFile =
+ java(
+ """
+ package android.platform.test.rule;
+
+ public class PlatinumRule {
+ public @interface Platinum {
+ String devices();
+ int bugId() default -1;
+ }
+ }
+ """
+ )
+ private val annotationsIgnoreStub: TestFile =
+ java(
+ """
+ package org.junit;
+
+ public @interface Ignore {
+ String value() default "";
+ }
+ """
+ )
+ private val stubs =
+ arrayOf(
+ filtersFlakyTestStub,
+ annotationsFlakyTestStub,
+ annotationsPlatinumStub,
+ annotationsIgnoreStub
+ )
+}
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
new file mode 100644
index 000000000000..95b700543f1e
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
@@ -0,0 +1,332 @@
+/*
+ * 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.internal.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+@Suppress("UnstableApiUsage")
+class DumpableNotRegisteredDetectorTest : SystemUILintDetectorTest() {
+ override fun getDetector(): Detector = DumpableNotRegisteredDetector()
+
+ override fun getIssues(): List<Issue> = listOf(DumpableNotRegisteredDetector.ISSUE)
+
+ @Test
+ fun classIsNotDumpable_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ class SomeClass() {
+ }
+ """
+ .trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_andRegisterIsCalled_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.dump.DumpManager;
+
+ public class SomeClass implements Dumpable {
+ SomeClass(DumpManager dumpManager) {
+ dumpManager.registerDumpable(this);
+ }
+
+ @Override
+ void dump(PrintWriter pw, String[] args) {
+ pw.println("testDump");
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_andRegisterNormalIsCalled_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.dump.DumpManager;
+
+ public class SomeClass implements Dumpable {
+ SomeClass(DumpManager dumpManager) {
+ dumpManager.registerNormalDumpable(this);
+ }
+
+ @Override
+ void dump(PrintWriter pw, String[] args) {
+ pw.println("testDump");
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_andRegisterCriticalIsCalled_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.dump.DumpManager;
+
+ public class SomeClass implements Dumpable {
+ SomeClass(DumpManager dumpManager) {
+ dumpManager.registerCriticalDumpable(this);
+ }
+
+ @Override
+ void dump(PrintWriter pw, String[] args) {
+ pw.println("testDump");
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_noRegister_violation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+
+ public class SomeClass implements Dumpable {
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expect(
+ ("""
+ src/test/pkg/SomeClass.java:5: Warning: Any class implementing Dumpable must call DumpManager.registerNormalDumpable or DumpManager.registerCriticalDumpable [DumpableNotRegistered]
+ public class SomeClass implements Dumpable {
+ ~~~~~~~~~
+ 0 errors, 1 warnings
+ """)
+ .trimIndent()
+ )
+ }
+
+ @Test
+ fun classIsDumpable_usesNotDumpManagerMethod_violation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.OtherRegistrationObject;
+
+ public class SomeClass implements Dumpable {
+ public SomeClass(OtherRegistrationObject otherRegistrationObject) {
+ otherRegistrationObject.registerDumpable(this);
+ }
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expect(
+ ("""
+ src/test/pkg/SomeClass.java:6: Warning: Any class implementing Dumpable must call DumpManager.registerNormalDumpable or DumpManager.registerCriticalDumpable [DumpableNotRegistered]
+ public class SomeClass implements Dumpable {
+ ~~~~~~~~~
+ 0 errors, 1 warnings
+ """)
+ .trimIndent()
+ )
+ }
+
+ @Test
+ fun classIsDumpableAndCoreStartable_noRegister_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.CoreStartable;
+
+ public class SomeClass implements Dumpable, CoreStartable {
+ @Override
+ public void start() {
+ }
+
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsAbstract_noRegister_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+
+ public abstract class SomeClass implements Dumpable {
+ void abstractMethodHere();
+
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ companion object {
+ private val DUMPABLE_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui;
+
+ import com.android.systemui.dump.DumpManager;
+ import java.io.PrintWriter;
+
+ public interface Dumpable {
+ void dump();
+ }
+ """
+ )
+ .indented()
+
+ private val DUMP_MANAGER_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui.dump;
+
+ public interface DumpManager {
+ void registerDumpable(Dumpable module);
+ void registerNormalDumpable(Dumpable module);
+ void registerCriticalDumpable(Dumpable module);
+ }
+ """
+ )
+ .indented()
+
+ private val OTHER_REGISTRATION_OBJECT_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui;
+
+ public interface OtherRegistrationObject {
+ void registerDumpable(Dumpable module);
+ }
+ """
+ )
+ .indented()
+
+ private val CORE_STARTABLE_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui;
+
+ public interface CoreStartable {
+ void start();
+ }
+ """
+ )
+ .indented()
+
+ private val stubs =
+ arrayOf(
+ DUMPABLE_STUB,
+ DUMP_MANAGER_STUB,
+ OTHER_REGISTRATION_OBJECT_STUB,
+ CORE_STARTABLE_STUB,
+ )
+ }
+}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt b/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
index a02954ab4800..08ab1462b161 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
@@ -78,11 +78,10 @@ interface SystemUiController {
* Set the status bar color.
*
* @param color The **desired** [Color] to set. This may require modification if running on an
- * API level that only supports white status bar icons.
+ * API level that only supports white status bar icons.
* @param darkIcons Whether dark status bar icons would be preferable.
* @param transformColorForLightContent A lambda which will be invoked to transform [color] if
- * dark icons were requested but are not available. Defaults to applying a black scrim.
- *
+ * dark icons were requested but are not available. Defaults to applying a black scrim.
* @see statusBarDarkContentEnabled
*/
fun setStatusBarColor(
@@ -95,16 +94,15 @@ interface SystemUiController {
* Set the navigation bar color.
*
* @param color The **desired** [Color] to set. This may require modification if running on an
- * API level that only supports white navigation bar icons. Additionally this will be ignored
- * and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or the
- * system UI automatically applies background protection in other navigation modes.
+ * API level that only supports white navigation bar icons. Additionally this will be ignored
+ * and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or
+ * the system UI automatically applies background protection in other navigation modes.
* @param darkIcons Whether dark navigation bar icons would be preferable.
* @param navigationBarContrastEnforced Whether the system should ensure that the navigation bar
- * has enough contrast when a fully transparent background is requested. Only supported on API
- * 29+.
+ * has enough contrast when a fully transparent background is requested. Only supported on API
+ * 29+.
* @param transformColorForLightContent A lambda which will be invoked to transform [color] if
- * dark icons were requested but are not available. Defaults to applying a black scrim.
- *
+ * dark icons were requested but are not available. Defaults to applying a black scrim.
* @see navigationBarDarkContentEnabled
* @see navigationBarContrastEnforced
*/
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
index cfc38df08b0a..d4a81f9c765d 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
@@ -255,7 +255,9 @@ fun Expandable(
.onGloballyPositioned {
controller.boundsInComposeViewRoot.value = it.boundsInRoot()
}
- ) { wrappedContent(controller.expandable) }
+ ) {
+ wrappedContent(controller.expandable)
+ }
}
else -> {
val clickModifier =
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
index edb10c7d392f..767756e17747 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
@@ -156,9 +156,9 @@ internal class ExpandableControllerImpl(
* Create a [LaunchAnimator.Controller] that is going to be used to drive an activity or dialog
* animation. This controller will:
* 1. Compute the start/end animation state using [boundsInComposeViewRoot] and the location of
- * composeViewRoot on the screen.
+ * composeViewRoot on the screen.
* 2. Update [animatorState] with the current animation state if we are animating, or null
- * otherwise.
+ * otherwise.
*/
private fun launchController(): LaunchAnimator.Controller {
return object : LaunchAnimator.Controller {
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
index eb9d62506faa..a80a1f934dab 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
@@ -86,21 +86,20 @@ object PagerDefaults {
/**
* A horizontally scrolling layout that allows users to flip between items to the left and right.
*
- * @sample com.google.accompanist.sample.pager.HorizontalPagerSample
- *
* @param count the number of pages.
* @param modifier the modifier to apply to this layout.
* @param state the state object to be used to control or observe the pager's state.
* @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the end to the start and [PagerState.currentPage] == 0 will mean the first item is
- * located at the end.
+ * composed from the end to the start and [PagerState.currentPage] == 0 will mean the first item
+ * is located at the end.
* @param itemSpacing horizontal spacing to add between items.
* @param flingBehavior logic describing fling behavior.
* @param key the scroll position will be maintained based on the key, which means if you add/remove
- * items before the current visible item the item with the given key will be kept as the first
- * visible one.
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param content a block which describes the content. Inside this block you can reference
- * [PagerScope.currentPage] and other properties in [PagerScope].
+ * [PagerScope.currentPage] and other properties in [PagerScope].
+ * @sample com.google.accompanist.sample.pager.HorizontalPagerSample
*/
@ExperimentalPagerApi
@Composable
@@ -134,21 +133,20 @@ fun HorizontalPager(
/**
* A vertically scrolling layout that allows users to flip between items to the top and bottom.
*
- * @sample com.google.accompanist.sample.pager.VerticalPagerSample
- *
* @param count the number of pages.
* @param modifier the modifier to apply to this layout.
* @param state the state object to be used to control or observe the pager's state.
* @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the bottom to the top and [PagerState.currentPage] == 0 will mean the first item is
- * located at the bottom.
+ * composed from the bottom to the top and [PagerState.currentPage] == 0 will mean the first item
+ * is located at the bottom.
* @param itemSpacing vertical spacing to add between items.
* @param flingBehavior logic describing fling behavior.
* @param key the scroll position will be maintained based on the key, which means if you add/remove
- * items before the current visible item the item with the given key will be kept as the first
- * visible one.
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param content a block which describes the content. Inside this block you can reference
- * [PagerScope.currentPage] and other properties in [PagerScope].
+ * [PagerScope.currentPage] and other properties in [PagerScope].
+ * @sample com.google.accompanist.sample.pager.VerticalPagerSample
*/
@ExperimentalPagerApi
@Composable
@@ -246,7 +244,9 @@ internal fun Pager(
// Constraint the content to be <= than the size of the pager.
.fillParentMaxHeight()
.wrapContentSize()
- ) { pagerScope.content(page) }
+ ) {
+ pagerScope.content(page)
+ }
}
}
} else {
@@ -272,7 +272,9 @@ internal fun Pager(
// Constraint the content to be <= than the size of the pager.
.fillParentMaxWidth()
.wrapContentSize()
- ) { pagerScope.content(page) }
+ ) {
+ pagerScope.content(page)
+ }
}
}
}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
index 2e6ae78b43c7..1822a68f1e77 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
@@ -198,7 +198,7 @@ class PagerState(
*
* @param page the page to animate to. Must be between 0 and [pageCount] (inclusive).
* @param pageOffset the percentage of the page width to offset, from the start of [page]. Must
- * be in the range 0f..1f.
+ * be in the range 0f..1f.
*/
suspend fun animateScrollToPage(
@IntRange(from = 0) page: Int,
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
index 23122de56758..98140295306a 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
@@ -44,11 +44,11 @@ internal object SnappingFlingBehaviorDefaults {
/**
* Create and remember a snapping [FlingBehavior] to be used with [LazyListState].
*
- * TODO: move this to a new module and make it public
- *
* @param lazyListState The [LazyListState] to update.
* @param decayAnimationSpec The decay animation spec to use for decayed flings.
* @param snapAnimationSpec The animation spec to use when snapping.
+ *
+ * TODO: move this to a new module and make it public
*/
@Composable
internal fun rememberSnappingFlingBehavior(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
index 3eeadae5385f..a74e56b6e2f2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
@@ -60,7 +60,7 @@ import com.android.systemui.people.ui.viewmodel.PeopleViewModel
*
* @param viewModel the [PeopleViewModel] that should be composed.
* @param onResult the callback called with the result of this screen. Callers should usually finish
- * the Activity/Fragment/View hosting this Composable once a result is available.
+ * the Activity/Fragment/View hosting this Composable once a result is available.
*/
@Composable
fun PeopleScreen(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
index 3f590df697cb..0484ff475cdf 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
@@ -79,7 +79,9 @@ internal fun PeopleScreenEmpty(
containerColor = androidColors.colorAccentPrimary,
contentColor = androidColors.textColorOnAccent,
)
- ) { Text(stringResource(R.string.got_it)) }
+ ) {
+ Text(stringResource(R.string.got_it))
+ }
}
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index ab36d5899739..00c0a0b3e7b3 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -38,6 +38,7 @@ import kotlinx.coroutines.launch
private val TAG = ClockRegistry::class.simpleName!!
private const val DEBUG = true
+private val KEY_TIMESTAMP = "appliedTimestamp"
/** ClockRegistry aggregates providers and plugins */
open class ClockRegistry(
@@ -134,9 +135,9 @@ open class ClockRegistry(
assertNotMainThread()
try {
- value?._applied_timestamp = System.currentTimeMillis()
- val json = ClockSettings.serialize(value)
+ value?.metadata?.put(KEY_TIMESTAMP, System.currentTimeMillis())
+ val json = ClockSettings.serialize(value)
if (handleAllUsers) {
Settings.Secure.putStringForUser(
context.contentResolver,
@@ -172,7 +173,7 @@ open class ClockRegistry(
clockChangeListeners.forEach(func)
}
- private fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) {
+ public fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) {
scope.launch(bgDispatcher) { applySettings(mutator(settings ?: ClockSettings())) }
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 2a40f5c70420..4df7a44d3e1d 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -95,7 +95,7 @@ class DefaultClockController(
open inner class DefaultClockFaceController(
override val view: AnimatableClockView,
- val seedColor: Int?,
+ var seedColor: Int?,
) : ClockFaceController {
// MAGENTA is a placeholder, and will be assigned correctly in initialize
@@ -111,9 +111,9 @@ class DefaultClockController(
init {
if (seedColor != null) {
- currentColor = seedColor
+ currentColor = seedColor!!
}
- view.setColors(currentColor, currentColor)
+ view.setColors(DOZE_COLOR, currentColor)
}
override val events =
@@ -141,7 +141,7 @@ class DefaultClockController(
fun updateColor() {
val color =
if (seedColor != null) {
- seedColor
+ seedColor!!
} else if (isRegionDark) {
resources.getColor(android.R.color.system_accent1_100)
} else {
@@ -194,6 +194,14 @@ class DefaultClockController(
smallClock.updateColor()
}
+ override fun onSeedColorChanged(seedColor: Int?) {
+ largeClock.seedColor = seedColor
+ smallClock.seedColor = seedColor
+
+ largeClock.updateColor()
+ smallClock.updateColor()
+ }
+
override fun onLocaleChanged(locale: Locale) {
val nf = NumberFormat.getInstance(locale)
if (nf.format(FORMAT_NUMBER.toLong()) == burmeseNumerals) {
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
index c120876a7a63..0d880759bd09 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
@@ -51,7 +51,7 @@ object CustomizationProviderContract {
*
* Supported operations:
* - Query - to know which slots are available, query the [SlotTable.URI] [Uri]. The result
- * set will contain rows with the [SlotTable.Columns] columns.
+ * set will contain rows with the [SlotTable.Columns] columns.
*/
object SlotTable {
const val TABLE_NAME = "slots"
@@ -74,8 +74,8 @@ object CustomizationProviderContract {
*
* Supported operations:
* - Query - to know about all the affordances that are available on the device, regardless
- * of which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result
- * set will contain rows, each with the columns specified in [AffordanceTable.Columns].
+ * of which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result
+ * set will contain rows, each with the columns specified in [AffordanceTable.Columns].
*/
object AffordanceTable {
const val TABLE_NAME = "affordances"
@@ -128,14 +128,14 @@ object CustomizationProviderContract {
*
* Supported operations:
* - Insert - to insert an affordance and place it in a slot, insert values for the columns
- * into the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the system.
- * Selecting a new affordance for a slot that is already full will automatically remove the
- * oldest affordance from the slot.
+ * into the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the
+ * system. Selecting a new affordance for a slot that is already full will automatically
+ * remove the oldest affordance from the slot.
* - Query - to know which affordances are set on which slots, query the
- * [SelectionTable.URI] [Uri]. The result set will contain rows, each of which with the
- * columns from [SelectionTable.Columns].
+ * [SelectionTable.URI] [Uri]. The result set will contain rows, each of which with the
+ * columns from [SelectionTable.Columns].
* - Delete - to unselect an affordance, removing it from a slot, delete from the
- * [SelectionTable.URI] [Uri], passing in values for each column.
+ * [SelectionTable.URI] [Uri], passing in values for each column.
*/
object SelectionTable {
const val TABLE_NAME = "selections"
@@ -160,7 +160,7 @@ object CustomizationProviderContract {
*
* Supported operations:
* - Query - to know the values of flags, query the [FlagsTable.URI] [Uri]. The result set will
- * contain rows, each of which with the columns from [FlagsTable.Columns].
+ * contain rows, each of which with the columns from [FlagsTable.Columns].
*/
object FlagsTable {
const val TABLE_NAME = "flags"
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index 943d7996dd89..8a6fc5dc53f1 100644
--- a/packages/SystemUI/ktfmt_includes.txt
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -1,28 +1,20 @@
+packages/SystemUI
-packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
-packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/BindServiceViaContextDetector.kt
-packages/SystemUI/checks/src/com/android/internal/systemui/lint/BroadcastSentViaContextDetector.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/GetMainLooperViaContextDetector.kt
-packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt
-packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/BindServiceViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/BroadcastSentViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/GetMainLooperViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt
+-packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+-packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
-packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
--packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt
+-packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/View.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagListenable.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSerializer.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSettingsHelper.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerManager.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt
@@ -35,8 +27,6 @@
-packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt
-packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
-packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt
--packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
--packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
-packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
-packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherAnchor.kt
-packages/SystemUI/src/com/android/keyguard/clock/ClockPalette.kt
@@ -65,12 +55,10 @@
-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt
-packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt
--packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
@@ -80,7 +68,6 @@
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsHapticsSimulator.kt
--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayParams.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
@@ -93,8 +80,6 @@
-packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
-packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
-packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
--packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
--packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt
-packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
-packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
-packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLogger.kt
@@ -102,7 +87,6 @@
-packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
-packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt
-packages/SystemUI/src/com/android/systemui/controls/TooltipManager.kt
--packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
-packages/SystemUI/src/com/android/systemui/controls/controller/ControlInfo.kt
-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -132,6 +116,7 @@
-packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
-packages/SystemUI/src/com/android/systemui/controls/management/ManagementPageIndicator.kt
-packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
-packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt
-packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt
-packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt
@@ -162,7 +147,6 @@
-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
-packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt
--packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
-packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
-packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt
-packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
@@ -172,20 +156,16 @@
-packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
-packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt
-packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+-packages/SystemUI/src/com/android/systemui/flags/Flags.kt
-packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
-packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
-packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
--packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
-packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
--packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
--packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
--packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
--packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
-packages/SystemUI/src/com/android/systemui/media/MediaProjectionCaptureTarget.kt
--packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt
-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
@@ -202,6 +182,11 @@
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorResultHandler.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTasksAdapter.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt
-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
@@ -220,8 +205,6 @@
-packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
-packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
-packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
--packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
--packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
-packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
-packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
-packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt
@@ -237,7 +220,6 @@
-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt
-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialogEventLogger.kt
-packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
--packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
-packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
-packages/SystemUI/src/com/android/systemui/qs/tileimpl/IgnorableChildLinearLayout.kt
-packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -245,10 +227,6 @@
-packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
-packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
-packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleShaderUtilLibrary.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
--packages/SystemUI/src/com/android/systemui/ripple/SdfShaderLibrary.kt
-packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt
-packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
@@ -259,23 +237,21 @@
-packages/SystemUI/src/com/android/systemui/settings/UserContentResolverProvider.kt
-packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt
-packages/SystemUI/src/com/android/systemui/settings/UserFileManager.kt
--packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt
-packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
-packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
-packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
-packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
--packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
-packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt
--packages/SystemUI/src/com/android/systemui/shade/NotifPanelEvents.kt
-packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
-packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
-packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeHeightLogger.kt
-packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt
-packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
-packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
--packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
-packages/SystemUI/src/com/android/systemui/smartspace/SmartspacePrecondition.kt
-packages/SystemUI/src/com/android/systemui/smartspace/SmartspaceTargetFilter.kt
-packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
@@ -284,10 +260,8 @@
-packages/SystemUI/src/com/android/systemui/smartspace/preconditions/LockscreenPrecondition.kt
-packages/SystemUI/src/com/android/systemui/statusbar/AbstractLockscreenShadeTransitionController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarWifiView.kt
-packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
-packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
-packages/SystemUI/src/com/android/systemui/statusbar/LockScreenShadeOverScroller.kt
-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeScrimTransitionController.kt
@@ -311,10 +285,12 @@
-packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt
-packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
-packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt
-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureHandler.kt
-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
@@ -325,7 +301,6 @@
-packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManagerLogger.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
@@ -396,6 +371,9 @@
-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferLogger.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconBuilder.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -403,6 +381,7 @@
-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
@@ -444,13 +423,10 @@
-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt
-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/ShadeStateListener.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserInfoTracker.kt
-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/ConnectivitySlots.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
-packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
@@ -470,19 +446,17 @@
-packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt
-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
--packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
+-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
-packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarRootView.kt
-packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
-packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
-packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt
+-packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
-packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt
-packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt
--packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt
--packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
-packages/SystemUI/src/com/android/systemui/unfold/UnfoldProgressProvider.kt
-packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
--packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
-packages/SystemUI/src/com/android/systemui/user/UserSwitcherPopupMenu.kt
-packages/SystemUI/src/com/android/systemui/user/UserSwitcherRootView.kt
-packages/SystemUI/src/com/android/systemui/util/AsyncActivityLauncher.kt
@@ -509,7 +483,6 @@
-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
-packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
--packages/SystemUI/src/com/android/systemui/util/collection/RingBuffer.kt
-packages/SystemUI/src/com/android/systemui/util/concurrency/Execution.kt
-packages/SystemUI/src/com/android/systemui/util/concurrency/PendingTasksContainer.kt
-packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt
@@ -517,6 +490,7 @@
-packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
-packages/SystemUI/src/com/android/systemui/util/kotlin/IpcSerializer.kt
-packages/SystemUI/src/com/android/systemui/util/kotlin/nullability.kt
+-packages/SystemUI/src/com/android/systemui/util/recycler/HorizontalSpacerItemDecoration.kt
-packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt
-packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt
-packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
@@ -525,7 +499,6 @@
-packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt
--packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
@@ -550,7 +523,6 @@
-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt
--packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
@@ -569,7 +541,6 @@
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
@@ -579,8 +550,8 @@
-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoritesModelTest.kt
--packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
-packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
-packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
@@ -596,13 +567,16 @@
-packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
-packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/lifecycle/InstantTaskExecutorRule.kt
--packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
-packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyChipBuilderTest.kt
@@ -610,7 +584,6 @@
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/QSContainerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt
@@ -641,36 +614,29 @@
-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/ripple/RippleViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordDialogTest.kt
-packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageCaptureImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
--packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/DisableFlagsLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -683,10 +649,12 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/VibratorHelperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographerTest.kt
@@ -719,7 +687,6 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
@@ -733,8 +700,7 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/panelstate/ShadeExpansionStateManagerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
@@ -744,7 +710,6 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
@@ -753,40 +718,36 @@
-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
--packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
--packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
-packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt
-packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
--packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/FakeSharedPreferencesTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/FloatingContentCoordinatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt
--packages/SystemUI/tests/src/com/android/systemui/util/collection/RingBufferTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/drawable/DrawableSizeTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/IpcSerializerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/SuspendUtilTests.kt
-packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt
--packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSharedPreferences.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index 1c2f38beb867..babe5700a01c 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -112,8 +112,11 @@ interface ClockEvents {
/** Call whenever the color palette should update */
fun onColorPaletteChanged(resources: Resources) {}
+ /** Call if the seed color has changed and should be updated */
+ fun onSeedColorChanged(seedColor: Int?) {}
+
/** Call whenever the weather data should update */
- fun onWeatherDataChanged(data: Weather) {}
+ fun onWeatherDataChanged(data: WeatherData) {}
}
/** Methods which trigger various clock animations */
@@ -189,12 +192,13 @@ data class ClockSettings(
val clockId: ClockId? = null,
val seedColor: Int? = null,
) {
- var _applied_timestamp: Long? = null
+ // Exclude metadata from equality checks
+ var metadata: JSONObject = JSONObject()
companion object {
private val KEY_CLOCK_ID = "clockId"
private val KEY_SEED_COLOR = "seedColor"
- private val KEY_TIMESTAMP = "_applied_timestamp"
+ private val KEY_METADATA = "metadata"
fun serialize(setting: ClockSettings?): String {
if (setting == null) {
@@ -204,7 +208,7 @@ data class ClockSettings(
return JSONObject()
.put(KEY_CLOCK_ID, setting.clockId)
.put(KEY_SEED_COLOR, setting.seedColor)
- .put(KEY_TIMESTAMP, setting._applied_timestamp)
+ .put(KEY_METADATA, setting.metadata)
.toString()
}
@@ -216,11 +220,11 @@ data class ClockSettings(
val json = JSONObject(jsonStr)
val result =
ClockSettings(
- json.getString(KEY_CLOCK_ID),
+ if (!json.isNull(KEY_CLOCK_ID)) json.getString(KEY_CLOCK_ID) else null,
if (!json.isNull(KEY_SEED_COLOR)) json.getInt(KEY_SEED_COLOR) else null
)
- if (!json.isNull(KEY_TIMESTAMP)) {
- result._applied_timestamp = json.getLong(KEY_TIMESTAMP)
+ if (!json.isNull(KEY_METADATA)) {
+ result.metadata = json.getJSONObject(KEY_METADATA)
}
return result
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/Weather.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/Weather.kt
deleted file mode 100644
index 302f17556bc7..000000000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/Weather.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.android.systemui.plugins
-
-import android.os.Bundle
-
-class Weather(val conditions: WeatherStateIcon, val temperature: Int, val isCelsius: Boolean) {
- companion object {
- private const val TAG = "Weather"
- private const val WEATHER_STATE_ICON_KEY = "weather_state_icon_extra_key"
- private const val TEMPERATURE_VALUE_KEY = "temperature_value_extra_key"
- private const val TEMPERATURE_UNIT_KEY = "temperature_unit_extra_key"
- private const val INVALID_TEMPERATURE = Int.MIN_VALUE
-
- fun fromBundle(extras: Bundle): Weather? {
- val icon =
- WeatherStateIcon.fromInt(
- extras.getInt(WEATHER_STATE_ICON_KEY, WeatherStateIcon.UNKNOWN_ICON.id)
- )
- if (icon == null || icon == WeatherStateIcon.UNKNOWN_ICON) {
- return null
- }
- val temperature = extras.getInt(TEMPERATURE_VALUE_KEY, INVALID_TEMPERATURE)
- if (temperature == INVALID_TEMPERATURE) {
- return null
- }
- return Weather(icon, temperature, extras.getBoolean(TEMPERATURE_UNIT_KEY))
- }
- }
-
- enum class WeatherStateIcon(val id: Int) {
- UNKNOWN_ICON(0),
-
- // Clear, day & night.
- SUNNY(1),
- CLEAR_NIGHT(2),
-
- // Mostly clear, day & night.
- MOSTLY_SUNNY(3),
- MOSTLY_CLEAR_NIGHT(4),
-
- // Partly cloudy, day & night.
- PARTLY_CLOUDY(5),
- PARTLY_CLOUDY_NIGHT(6),
-
- // Mostly cloudy, day & night.
- MOSTLY_CLOUDY_DAY(7),
- MOSTLY_CLOUDY_NIGHT(8),
- CLOUDY(9),
- HAZE_FOG_DUST_SMOKE(10),
- DRIZZLE(11),
- HEAVY_RAIN(12),
- SHOWERS_RAIN(13),
-
- // Scattered showers, day & night.
- SCATTERED_SHOWERS_DAY(14),
- SCATTERED_SHOWERS_NIGHT(15),
-
- // Isolated scattered thunderstorms, day & night.
- ISOLATED_SCATTERED_TSTORMS_DAY(16),
- ISOLATED_SCATTERED_TSTORMS_NIGHT(17),
- STRONG_TSTORMS(18),
- BLIZZARD(19),
- BLOWING_SNOW(20),
- FLURRIES(21),
- HEAVY_SNOW(22),
-
- // Scattered snow showers, day & night.
- SCATTERED_SNOW_SHOWERS_DAY(23),
- SCATTERED_SNOW_SHOWERS_NIGHT(24),
- SNOW_SHOWERS_SNOW(25),
- MIXED_RAIN_HAIL_RAIN_SLEET(26),
- SLEET_HAIL(27),
- TORNADO(28),
- TROPICAL_STORM_HURRICANE(29),
- WINDY_BREEZY(30),
- WINTRY_MIX_RAIN_SNOW(31);
-
- companion object {
- fun fromInt(value: Int) = values().firstOrNull { it.id == value }
- }
- }
-
- override fun toString(): String {
- return "$conditions $temperature${if (isCelsius) "C" else "F"}"
- }
-}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/WeatherData.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/WeatherData.kt
new file mode 100644
index 000000000000..52dfc55c105d
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/WeatherData.kt
@@ -0,0 +1,107 @@
+package com.android.systemui.plugins
+
+import android.os.Bundle
+import androidx.annotation.VisibleForTesting
+
+class WeatherData
+private constructor(
+ val description: String,
+ val state: WeatherStateIcon,
+ val useCelsius: Boolean,
+ val temperature: Int,
+) {
+ companion object {
+ private const val TAG = "WeatherData"
+ @VisibleForTesting const val DESCRIPTION_KEY = "description"
+ @VisibleForTesting const val STATE_KEY = "state"
+ @VisibleForTesting const val USE_CELSIUS_KEY = "use_celsius"
+ @VisibleForTesting const val TEMPERATURE_KEY = "temperature"
+ private const val INVALID_WEATHER_ICON_STATE = -1
+
+ fun fromBundle(extras: Bundle): WeatherData? {
+ val description = extras.getString(DESCRIPTION_KEY)
+ val state =
+ WeatherStateIcon.fromInt(extras.getInt(STATE_KEY, INVALID_WEATHER_ICON_STATE))
+ val temperature = readIntFromBundle(extras, TEMPERATURE_KEY)
+ return if (
+ description == null ||
+ state == null ||
+ !extras.containsKey(USE_CELSIUS_KEY) ||
+ temperature == null
+ )
+ null
+ else
+ WeatherData(
+ description = description,
+ state = state,
+ useCelsius = extras.getBoolean(USE_CELSIUS_KEY),
+ temperature = temperature
+ )
+ }
+
+ private fun readIntFromBundle(extras: Bundle, key: String): Int? =
+ try {
+ extras.getString(key).toInt()
+ } catch (e: Exception) {
+ null
+ }
+ }
+
+ enum class WeatherStateIcon(val id: Int) {
+ UNKNOWN_ICON(0),
+
+ // Clear, day & night.
+ SUNNY(1),
+ CLEAR_NIGHT(2),
+
+ // Mostly clear, day & night.
+ MOSTLY_SUNNY(3),
+ MOSTLY_CLEAR_NIGHT(4),
+
+ // Partly cloudy, day & night.
+ PARTLY_CLOUDY(5),
+ PARTLY_CLOUDY_NIGHT(6),
+
+ // Mostly cloudy, day & night.
+ MOSTLY_CLOUDY_DAY(7),
+ MOSTLY_CLOUDY_NIGHT(8),
+ CLOUDY(9),
+ HAZE_FOG_DUST_SMOKE(10),
+ DRIZZLE(11),
+ HEAVY_RAIN(12),
+ SHOWERS_RAIN(13),
+
+ // Scattered showers, day & night.
+ SCATTERED_SHOWERS_DAY(14),
+ SCATTERED_SHOWERS_NIGHT(15),
+
+ // Isolated scattered thunderstorms, day & night.
+ ISOLATED_SCATTERED_TSTORMS_DAY(16),
+ ISOLATED_SCATTERED_TSTORMS_NIGHT(17),
+ STRONG_TSTORMS(18),
+ BLIZZARD(19),
+ BLOWING_SNOW(20),
+ FLURRIES(21),
+ HEAVY_SNOW(22),
+
+ // Scattered snow showers, day & night.
+ SCATTERED_SNOW_SHOWERS_DAY(23),
+ SCATTERED_SNOW_SHOWERS_NIGHT(24),
+ SNOW_SHOWERS_SNOW(25),
+ MIXED_RAIN_HAIL_RAIN_SLEET(26),
+ SLEET_HAIL(27),
+ TORNADO(28),
+ TROPICAL_STORM_HURRICANE(29),
+ WINDY_BREEZY(30),
+ WINTRY_MIX_RAIN_SNOW(31);
+
+ companion object {
+ fun fromInt(value: Int) = values().firstOrNull { it.id == value }
+ }
+ }
+
+ override fun toString(): String {
+ val unit = if (useCelsius) "C" else "F"
+ return "$state (\"$description\") $temperature°$unit"
+ }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
index e99b2149bc1d..3e34885a6d9c 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
@@ -35,7 +35,6 @@ import kotlin.math.max
* as the result of taking a bug report).
*
* You can dump the entire buffer at any time by running:
- *
* ```
* $ adb shell dumpsys activity service com.android.systemui/.SystemUIService <bufferName>
* ```
@@ -46,13 +45,11 @@ import kotlin.math.max
* locally (usually for debugging purposes).
*
* To enable logcat echoing for an entire buffer:
- *
* ```
* $ adb shell settings put global systemui/buffer/<bufferName> <level>
* ```
*
* To enable logcat echoing for a specific tag:
- *
* ```
* $ adb shell settings put global systemui/tag/<tag> <level>
* ```
@@ -64,10 +61,10 @@ import kotlin.math.max
* LogBufferFactory.
*
* @param name The name of this buffer, printed when the buffer is dumped and in some other
- * situations.
+ * situations.
* @param maxSize The maximum number of messages to keep in memory at any one time. Buffers start
- * out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches the
- * maximum, it behaves like a ring buffer.
+ * out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches
+ * the maximum, it behaves like a ring buffer.
*/
class LogBuffer
@JvmOverloads
@@ -116,22 +113,22 @@ constructor(
* initializer stored and converts it to a human-readable log message.
*
* @param tag A string of at most 23 characters, used for grouping logs into categories or
- * subjects. If this message is echoed to logcat, this will be the tag that is used.
+ * subjects. If this message is echoed to logcat, this will be the tag that is used.
* @param level Which level to log the message at, both to the buffer and to logcat if it's
- * echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
- * INFO level should be reserved for information that other parts of the system might care
- * about, leaving the specifics of code's day-to-day operations to DEBUG.
+ * echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
+ * INFO level should be reserved for information that other parts of the system might care
+ * about, leaving the specifics of code's day-to-day operations to DEBUG.
* @param messageInitializer A function that will be called immediately to store relevant data
- * on the log message. The value of `this` will be the LogMessage to be initialized.
+ * on the log message. The value of `this` will be the LogMessage to be initialized.
* @param messagePrinter A function that will be called if and when the message needs to be
- * dumped to logcat or a bug report. It should read the data stored by the initializer and
- * convert it to a human-readable string. The value of `this` will be the LogMessage to be
- * printed. **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and
- * NEVER any variables in its enclosing scope. Otherwise, the runtime will need to allocate a
- * new instance of the printer for each call, thwarting our attempts at avoiding any sort of
- * allocation.
+ * dumped to logcat or a bug report. It should read the data stored by the initializer and
+ * convert it to a human-readable string. The value of `this` will be the LogMessage to be
+ * printed. **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and
+ * NEVER any variables in its enclosing scope. Otherwise, the runtime will need to allocate a
+ * new instance of the printer for each call, thwarting our attempts at avoiding any sort of
+ * allocation.
* @param exception Provide any exception that need to be logged. This is saved as
- * [LogMessage.exception]
+ * [LogMessage.exception]
*/
@JvmOverloads
inline fun log(
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
index faf1b78c598d..7a125ac14ea1 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
@@ -28,7 +28,6 @@ import android.provider.Settings
* Version of [LogcatEchoTracker] for debuggable builds
*
* The log level of individual buffers or tags can be controlled via global settings:
- *
* ```
* # Echo any message to <bufferName> of <level> or higher
* $ adb shell settings put global systemui/buffer/<bufferName> <level>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index 1d28c63f8398..c0b69c169ccd 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -189,10 +189,12 @@ public interface QSTile {
/** Get the text for secondaryLabel. */
public String getSecondaryLabel(String stateText) {
- if (TextUtils.isEmpty(secondaryLabel)) {
+ // Use a local reference as the value might change from other threads
+ CharSequence localSecondaryLabel = secondaryLabel;
+ if (TextUtils.isEmpty(localSecondaryLabel)) {
return stateText;
}
- return secondaryLabel.toString();
+ return localSecondaryLabel.toString();
}
public boolean copyTo(State other) {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
index 68d78907f028..4773f54a079e 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
@@ -30,7 +30,7 @@ import kotlin.math.max
*
* @param maxSize The maximum size the buffer can grow to before it begins functioning as a ring.
* @param factory A function that creates a fresh instance of T. Used by the buffer while it's
- * growing to [maxSize].
+ * growing to [maxSize].
*/
class RingBuffer<T>(private val maxSize: Int, private val factory: () -> T) : Iterable<T> {
diff --git a/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png
deleted file mode 100644
index 2e259c3e17c1..000000000000
--- a/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png
deleted file mode 100644
index f4de96adae30..000000000000
--- a/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png
index 7cf9e3699ceb..7cf9e3699ceb 100644
--- a/packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png
+++ b/packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml b/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
index 411fea5dd22d..48769fdebd99 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
@@ -14,10 +14,12 @@
~ limitations under the License
-->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:id="@+id/digit_text"
style="@style/Widget.TextView.NumPadKey.Digit"
+ android:autoSizeMaxTextSize="32sp"
+ android:autoSizeTextType="uniform"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index 7db0fe908ec0..728d861ab693 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
**
** Copyright 2012, The Android Open Source Project
**
@@ -17,185 +16,185 @@
*/
-->
<!-- This is the SIM PIN view that allows the user to enter a SIM PIN to unlock the device. -->
-<com.android.keyguard.KeyguardSimPinView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res-auto"
- android:id="@+id/keyguard_sim_pin_view"
- android:orientation="vertical"
+<com.android.keyguard.KeyguardSimPinView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/keyguard_sim_pin_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ androidprv:layout_maxWidth="@dimen/keyguard_security_width"
+ android:layout_gravity="center_horizontal|bottom">
+ <include layout="@layout/keyguard_bouncer_message_area"/>
+
+ <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
- androidprv:layout_maxWidth="@dimen/keyguard_security_width"
- android:layout_gravity="center_horizontal|bottom">
- <include layout="@layout/keyguard_bouncer_message_area" />
- <Space
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
- <ImageView
- android:id="@+id/keyguard_sim"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:tint="@color/background_protected"
- android:src="@drawable/ic_lockscreen_sim"/>
- <LinearLayout
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:layoutDirection="ltr">
+ <LinearLayout
+ android:id="@+id/pin_area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:gravity="center"
- android:layoutDirection="ltr"
- >
- <include layout="@layout/keyguard_esim_area"
- android:id="@+id/keyguard_esim_area"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <RelativeLayout
- android:id="@+id/row0"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="4dp"
- >
+ android:gravity="center_horizontal"
+ android:paddingTop="@dimen/num_pad_entry_row_margin_bottom"
+ android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:layout_constraintBottom_toTopOf="@+id/flow1"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toTopOf="parent">
+
+ <ImageView
+ android:id="@+id/keyguard_sim"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/ic_lockscreen_sim"
+ app:tint="@color/background_protected" />
+
+ <include
+ android:id="@+id/keyguard_esim_area"
+ layout="@layout/keyguard_esim_area"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
<com.android.keyguard.PasswordTextView
android:id="@+id/simPinEntry"
style="@style/Widget.TextView.Password"
android:layout_width="@dimen/keyguard_security_width"
android:layout_height="@dimen/keyguard_password_height"
- android:layout_centerHorizontal="true"
- android:layout_marginRight="72dp"
android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
- android:gravity="center"
- androidprv:scaledTextSize="@integer/scaled_password_text_size" />
- </RelativeLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key1"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="1"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key2"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="2"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key3"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="3"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key4"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="4"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key5"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="5"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key6"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="6"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key7"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="7"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key8"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="8"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key9"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="9"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- >
- <com.android.keyguard.NumPadButton
- android:id="@+id/delete_button"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- android:contentDescription="@string/keyboardview_keycode_delete"
- style="@style/NumPadKey.Delete"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key0"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="0"
- />
- <com.android.keyguard.NumPadButton
- android:id="@+id/key_enter"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- style="@style/NumPadKey.Enter"
- android:contentDescription="@string/keyboardview_keycode_enter"
- />
+ androidprv:scaledTextSize="@integer/scaled_password_text_size" />
</LinearLayout>
- </LinearLayout>
- <include layout="@layout/keyguard_eca"
- android:id="@+id/keyguard_selector_fade_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_gravity="bottom|center_horizontal"
- android:layout_marginTop="@dimen/keyguard_eca_top_margin"
- android:layout_marginBottom="2dp"
- android:gravity="center_horizontal"/>
+
+ <androidx.constraintlayout.helper.widget.Flow
+ android:id="@+id/flow1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="horizontal"
+ androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+ androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+ androidprv:flow_horizontalStyle="packed"
+ androidprv:flow_maxElementsWrap="3"
+ androidprv:flow_verticalBias="1.0"
+ androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:flow_verticalStyle="packed"
+ androidprv:flow_wrapMode="aligned"
+ androidprv:layout_constraintBottom_toBottomOf="parent"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toBottomOf="@id/pin_area" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/delete_button"
+ style="@style/NumPadKey.Delete"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key0"
+ android:contentDescription="@string/keyboardview_keycode_delete" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/key_enter"
+ style="@style/NumPadKey.Enter"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:contentDescription="@string/keyboardview_keycode_enter" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key2"
+ androidprv:digit="1"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key2"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key3"
+ androidprv:digit="2"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key3"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key4"
+ androidprv:digit="3"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key4"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key5"
+ androidprv:digit="4"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key5"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key6"
+ androidprv:digit="5"
+ androidprv:textView="@+id/simPinEntry" />
+
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key6"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key7"
+ androidprv:digit="6"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key7"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key8"
+ androidprv:digit="7"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key8"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key9"
+ androidprv:digit="8"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key9"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/delete_button"
+ androidprv:digit="9"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key0"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key_enter"
+ androidprv:digit="0"
+ androidprv:textView="@+id/simPinEntry" />
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <include
+ android:id="@+id/keyguard_selector_fade_container"
+ layout="@layout/keyguard_eca"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|center_horizontal"
+ android:layout_marginBottom="2dp"
+ android:layout_marginTop="@dimen/keyguard_eca_top_margin"
+ android:gravity="center_horizontal"
+ android:orientation="vertical" />
</com.android.keyguard.KeyguardSimPinView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index 422bd4c12e8e..7e24d1231aee 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -21,6 +21,7 @@
<com.android.keyguard.KeyguardSimPukView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_sim_puk_view"
android:orientation="vertical"
android:layout_width="match_parent"
@@ -29,173 +30,165 @@
android:layout_gravity="center_horizontal|bottom">
<include layout="@layout/keyguard_bouncer_message_area"/>
- <Space
+ <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_weight="1" />
-
- <ImageView
- android:id="@+id/keyguard_sim"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:tint="@color/background_protected"
- android:src="@drawable/ic_lockscreen_sim"/>
-
- <LinearLayout
+ android:layout_weight="1"
+ android:layoutDirection="ltr">
+ <LinearLayout
+ android:id="@+id/pin_area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:gravity="center"
- android:layoutDirection="ltr"
- >
- <include layout="@layout/keyguard_esim_area"
- android:id="@+id/keyguard_esim_area"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <RelativeLayout
- android:id="@+id/row0"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="4dp"
- >
+ android:gravity="center_horizontal"
+ android:paddingTop="@dimen/num_pad_entry_row_margin_bottom"
+ android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:layout_constraintBottom_toTopOf="@+id/flow1"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toTopOf="parent">
+
+ <ImageView
+ android:id="@+id/keyguard_sim"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/ic_lockscreen_sim"
+ app:tint="@color/background_protected" />
+
+ <include
+ android:id="@+id/keyguard_esim_area"
+ layout="@layout/keyguard_esim_area"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
<com.android.keyguard.PasswordTextView
android:id="@+id/pukEntry"
style="@style/Widget.TextView.Password"
android:layout_width="@dimen/keyguard_security_width"
android:layout_height="@dimen/keyguard_password_height"
- android:layout_centerHorizontal="true"
- android:layout_marginRight="72dp"
- android:contentDescription="@string/keyguard_accessibility_sim_puk_area"
- android:gravity="center"
- androidprv:scaledTextSize="@integer/scaled_password_text_size" />
- </RelativeLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key1"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="1"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key2"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="2"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key3"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="3"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key4"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="4"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key5"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="5"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key6"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="6"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key7"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="7"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key8"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="8"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key9"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="9"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
+ android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
android:layout_gravity="center_horizontal"
- >
- <com.android.keyguard.NumPadButton
- android:id="@+id/delete_button"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- android:contentDescription="@string/keyboardview_keycode_delete"
- style="@style/NumPadKey.Delete"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key0"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="0"
- />
- <com.android.keyguard.NumPadButton
- android:id="@+id/key_enter"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- style="@style/NumPadKey.Enter"
- android:contentDescription="@string/keyboardview_keycode_enter"
- />
+ androidprv:scaledTextSize="@integer/scaled_password_text_size" />
</LinearLayout>
- </LinearLayout>
+
+ <androidx.constraintlayout.helper.widget.Flow
+ android:id="@+id/flow1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="horizontal"
+ androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+ androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+ androidprv:flow_horizontalStyle="packed"
+ androidprv:flow_maxElementsWrap="3"
+ androidprv:flow_verticalBias="1.0"
+ androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:flow_verticalStyle="packed"
+ androidprv:flow_wrapMode="aligned"
+ androidprv:layout_constraintBottom_toBottomOf="parent"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toBottomOf="@id/pin_area" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/delete_button"
+ style="@style/NumPadKey.Delete"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key0"
+ android:contentDescription="@string/keyboardview_keycode_delete" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/key_enter"
+ style="@style/NumPadKey.Enter"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:contentDescription="@string/keyboardview_keycode_enter" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key2"
+ androidprv:digit="1"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key2"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key3"
+ androidprv:digit="2"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key3"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key4"
+ androidprv:digit="3"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key4"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key5"
+ androidprv:digit="4"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key5"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key6"
+ androidprv:digit="5"
+ androidprv:textView="@+id/pukEntry" />
+
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key6"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key7"
+ androidprv:digit="6"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key7"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key8"
+ androidprv:digit="7"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key8"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key9"
+ androidprv:digit="8"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key9"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/delete_button"
+ androidprv:digit="9"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key0"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key_enter"
+ androidprv:digit="0"
+ androidprv:textView="@+id/pukEntry" />
+ </androidx.constraintlayout.widget.ConstraintLayout>
<include layout="@layout/keyguard_eca"
android:id="@+id/keyguard_selector_fade_container"
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index d5dba42ef974..bf1e716ee37b 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -30,7 +30,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzen"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzea optimizatu da bateria ez kaltetzeko"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria ez kaltetzeko, kargatzeko modua optimizatu da"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Desblokeatzeko, sakatu Menua."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Ez dago SIM txartelik"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index fe72fe0b8837..2bb4a0312ce9 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -30,7 +30,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बैटरी को नुकसान से बचाने के लिए, उसकी चार्जिंग को ऑप्टिमाइज़ किया गया"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बैटरी को नुकसान से बचाने के लिए, चार्जिंग को ऑप्टिमाइज़ किया गया"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"लॉक खोलने के लिए मेन्यू दबाएं."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"कोई सिम कार्ड नहीं है"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index 390bfcbf4801..eb837b48c96c 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -30,7 +30,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電最適化済み(バッテリーを保護)"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • バッテリーを保護するために、充電が最適化されています"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"メニューからロックを解除できます。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ネットワークがロックされました"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM カードなし"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index 845af855d47d..8f3a98477050 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -30,7 +30,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядталуда"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядталуда"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Баяу зарядталуда"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны қорғау үшін, зарядтау оңтайландырылды"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны қорғау үшін зарядтау оңтайландырылды"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ашу үшін \"Мәзір\" пернесін басыңыз."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Желі құлыптаулы"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM картасы салынбаған"</string>
diff --git a/packages/SystemUI/res-keyguard/values-land/dimens.xml b/packages/SystemUI/res-keyguard/values-land/dimens.xml
index f1aa54412b3b..a4e7a5f12db4 100644
--- a/packages/SystemUI/res-keyguard/values-land/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-land/dimens.xml
@@ -27,6 +27,4 @@
<integer name="scaled_password_text_size">26</integer>
<dimen name="bouncer_user_switcher_y_trans">@dimen/status_bar_height</dimen>
- <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">0dp</dimen>
- <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index 46332909f6f8..08cc6e222591 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -30,7 +30,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充电"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在慢速充电"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 为保护电池,充电过程已优化"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 为保护电池,充电方式已优化"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按“菜单”即可解锁。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"网络已锁定"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"没有 SIM 卡"</string>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 6cc5b9d7b7e8..edd6eff92c1c 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -78,7 +78,7 @@
<!-- The vertical margin between the date and the owner info. -->
<!-- The translation for disappearing security views after having solved them. -->
- <dimen name="disappear_y_translation">-32dp</dimen>
+ <dimen name="disappear_y_translation">-50dp</dimen>
<!-- Dimens for animation for the Bouncer PIN view -->
<dimen name="pin_view_trans_y_entry">120dp</dimen>
@@ -123,9 +123,7 @@
<dimen name="bouncer_user_switcher_item_padding_vertical">10dp</dimen>
<dimen name="bouncer_user_switcher_item_padding_horizontal">12dp</dimen>
<dimen name="bouncer_user_switcher_header_padding_end">44dp</dimen>
- <dimen name="bouncer_user_switcher_y_trans">0dp</dimen>
- <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">0dp</dimen>
- <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen>
+ <dimen name="bouncer_user_switcher_y_trans">80dp</dimen>
<!-- 2 * the margin + size should equal the plus_margin -->
<dimen name="user_switcher_icon_large_margin">16dp</dimen>
diff --git a/packages/SystemUI/res-product/values-af/strings.xml b/packages/SystemUI/res-product/values-af/strings.xml
index 09c9127d3dde..a80362a89e5e 100644
--- a/packages/SystemUI/res-product/values-af/strings.xml
+++ b/packages/SystemUI/res-product/values-af/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Jy het die foon <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Die werkprofiel sal verwyder word, wat alle profieldata sal uitvee."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd geteken. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal jy gevra word om jou e-posrekening te gebruik om jou tablet te ontsluit.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%3$d</xliff:g> sekondes."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd geteken. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal jy gevra word om jou e-posrekening te gebruik om jou foon te ontsluit.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%3$d</xliff:g> sekondes."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Die vingerafdruksensor is op die aan/af-skakelaar. Dit is die plat knoppie langs die verhewe volumeknoppie aan die kant van die tablet.\n\nDie skerm skakel af wanneer iemand die aan/af-skakelaar druk."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Die vingerafdruksensor is op die aan/af-skakelaar. Dit is die plat knoppie langs die verhewe volumeknoppie aan die kant van die toestel.\n\nDie skerm skakel af wanneer iemand die aan/af-skakelaar druk."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Die vingerafdruksensor is op die aan/af-skakelaar. Dit is die plat knoppie langs die verhewe volumeknoppie aan die kant van die foon.\n\nDie skerm skakel af wanneer iemand die aan/af-skakelaar druk."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Ontsluit jou foon vir meer opsies"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Ontsluit jou tablet vir meer opsies"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ontsluit jou toestel vir meer opsies"</string>
diff --git a/packages/SystemUI/res-product/values-am/strings.xml b/packages/SystemUI/res-product/values-am/strings.xml
index c08e19472bff..722e61c9ee99 100644
--- a/packages/SystemUI/res-product/values-am/strings.xml
+++ b/packages/SystemUI/res-product/values-am/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ስልኩን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። የስራ መገለጫው ይወገዳል፣ ይህም ሁሉንም የመገለጫ ውሂብ ይሰርዛል።"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ጡባዊዎን እንዲከፍቱ ይጠየቃሉ።\n\n ከ<xliff:g id="NUMBER_2">%3$d</xliff:g> ከሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ስልክዎን እንዲከፍቱ ይጠየቃሉ።\n\nእባክዎ ከ<xliff:g id="NUMBER_2">%3$d</xliff:g> ሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"የጣት አሻራ ዳሳሹ የማብሪያ/ማጥፊያ ቁልፉ ላይ ነው። በጡባዊው ጫፍ ላይ ከፍ ካለው የድምፅ አዝራር ቀጥሎ ያለው ጠፍጣፋ አዝራር ነው።\n\nየማብሪያ/ማጥፊያ ቁልፉን መጫን ማያ ገጹን ያጠፋዋል።"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"የጣት አሻራ ዳሳሹ የማብሪያ/ማጥፊያ ቁልፉ ላይ ነው። በመሣሪያው ጫፍ ላይ ከፍ ካለው የድምፅ አዝራር ቀጥሎ ያለው ጠፍጣፋ አዝራር ነው።\n\nየማብሪያ/ማጥፊያ ቁልፉን መጫን ማያ ገጹን ያጠፋዋል።"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"የጣት አሻራ ዳሳሹ የማብሪያ/ማጥፊያ ቁልፉ ላይ ነው። በስልኩ ጫፍ ላይ ከፍ ካለው የድምፅ አዝራር ቀጥሎ ያለው ጠፍጣፋ አዝራር ነው።\n\nየማብሪያ/ማጥፊያ ቁልፉን መጫን ማያ ገጹን ያጠፋዋል።"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ለተጨማሪ አማራጮች የእርስዎን ስልክ ይክፈቱ"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ለተጨማሪ አማራጮች የእርስዎን ጡባዊ ይክፈቱ"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ለተጨማሪ አማራጮች የእርስዎን መሣሪያ ይክፈቱ"</string>
diff --git a/packages/SystemUI/res-product/values-ar/strings.xml b/packages/SystemUI/res-product/values-ar/strings.xml
index 8922c27a74ee..5386f41394a2 100644
--- a/packages/SystemUI/res-product/values-ar/strings.xml
+++ b/packages/SystemUI/res-product/values-ar/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة الملف الشخصي للعمل، ومن ثم يتم حذف جميع بياناته."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستُطالَب بفتح قفل الجهاز اللوحي باستخدام معلومات حساب بريد إلكتروني.\n\n يُرجى إعادة المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستُطالَب بفتح قفل الهاتف باستخدام حساب بريد إلكتروني.\n\n يُرجى إعادة المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"توجد أداة استشعار بصمة الإصبع على زر التشغيل. زر التشغيل هو الزر المسطّح بجانب زرّي التحكم بمستوى الصوت البارزين في الجزء الجانبي من الجهاز اللوحي.\n\nيؤدي الضغط على زر التشغيل إلى إطفاء الشاشة."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"توجد أداة استشعار بصمة الإصبع على زر التشغيل. زر التشغيل هو الزر المسطّح بجانب زرّي التحكم بمستوى الصوت البارزين في الجزء الجانبي من الجهاز.\n\nيؤدي الضغط على زر التشغيل إلى إطفاء الشاشة."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"توجد أداة استشعار بصمة الإصبع على زر التشغيل. زر التشغيل هو الزر المسطّح بجانب زرّي التحكم بمستوى الصوت البارزين في الجزء الجانبي من الهاتف.\n\nيؤدي الضغط على زر التشغيل إلى إطفاء الشاشة."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"يمكنك فتح قفل هاتفك للوصول إلى مزيد من الخيارات."</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"يمكنك فتح قفل جهازك اللوحي للوصول إلى مزيد من الخيارات."</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"يمكنك فتح قفل جهازك للوصول إلى مزيد من الخيارات."</string>
diff --git a/packages/SystemUI/res-product/values-as/strings.xml b/packages/SystemUI/res-product/values-as/strings.xml
index c8aedb3f6093..5d8f09e6526e 100644
--- a/packages/SystemUI/res-product/values-as/strings.xml
+++ b/packages/SystemUI/res-product/values-as/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলটোৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"আপুনি নিজৰ আনলক কৰা আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাক নিজৰ টেবলেটটো এটা ইমেইল একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ’ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পাছত পুনৰ চেষ্টা কৰক।"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"আপুনি নিজৰ আনলক কৰা আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাক নিজৰ ফ’নটো এটা ইমেইল একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ’ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পাছত পুনৰ চেষ্টা কৰক।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো পাৱাৰ বুটামটোত আছে। এইটো হৈছে টেবলেটটোৰ প্ৰান্তত থকা ভলিউম বঢ়োৱা বুটামটোৰ কাষত থকা সমতল বুটামটো।\n\nপাৱাৰ বুটাম টিপিলে স্ক্ৰীনখন অফ হৈ যায়।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো পাৱাৰ বুটামটোত আছে। এইটো হৈছে ডিভাইচটোৰ প্ৰান্তত থকা ভলিউম বঢ়োৱা বুটামটোৰ কাষত থকা সমতল বুটামটো।\n\nপাৱাৰ বুটাম টিপিলে স্ক্ৰীনখন অফ হৈ যায়।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো পাৱাৰ বুটামটোত আছে। এইটো হৈছে ফ’নটোৰ প্ৰান্তত থকা ভলিউম বঢ়োৱা বুটামটোৰ কাষত থকা সমতল বুটামটো।\n\nপাৱাৰ বুটাম টিপিলে স্ক্ৰীনখন অফ হৈ যায়।"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"অধিক বিকল্পৰ বাবে আপোনাৰ ফ’নটো আনলক কৰক"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"অধিক বিকল্পৰ বাবে আপোনাৰ টেবলেটটো আনলক কৰক"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"অধিক বিকল্পৰ বাবে আপোনাৰ ডিভাইচটো আনলক কৰক"</string>
diff --git a/packages/SystemUI/res-product/values-az/strings.xml b/packages/SystemUI/res-product/values-az/strings.xml
index fd514b3c71ba..e94a7e7793f2 100644
--- a/packages/SystemUI/res-product/values-az/strings.xml
+++ b/packages/SystemUI/res-product/values-az/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhd etmisiniz. İş profili silinəcək və bütün data ləğv ediləcək."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Kilid açma modelini <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra planşet kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra cəhd edin."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Kilid açma modelini artıq <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra telefon kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra cəhd edin."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Barmaq izi sensoru enerji düyməsinin üzərindədir. Bu, planşetin kənarındakı qabarıq səs düyməsinin yanındakı yastı düymədir.\n\nEnerji düyməsini basdıqda ekran sönür."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Barmaq izi sensoru enerji düyməsinin üzərindədir. Bu, cihazın kənarındakı qabarıq səs düyməsinin yanındakı yastı düymədir.\n\nEnerji düyməsini basdıqda ekran sönür."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Barmaq izi sensoru enerji düyməsinin üzərindədir. Bu, telefonun kənarındakı qabarıq səs düyməsinin yanındakı yastı düymədir.\n\nEnerji düyməsini basdıqda ekran sönür."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Daha çox seçim üçün telefonu kiliddən çıxarın"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Daha çox seçim üçün planşeti kiliddən çıxarın"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Daha çox seçim üçün cihazı kiliddən çıxarın"</string>
diff --git a/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
index 287b3f67b887..71993d67561a 100644
--- a/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Uklonićemo poslovni profil, čime se brišu svi podaci sa profila."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Netačno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, zatražićemo da otključate tablet pomoću imejl naloga.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Netačno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, zatražićemo da otključate telefon pomoću imejl naloga.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Senzor za otisak prsta se nalazi na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na ivici tableta.\n\nPritiskom na dugme za uključivanje isključuje se ekran."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Senzor za otisak prsta se nalazi na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na ivici uređaja.\n\nPritiskom na dugme za uključivanje isključuje se ekran."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Senzor za otisak prsta se nalazi na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na ivici telefona.\n\nPritiskom na dugme za uključivanje isključuje se ekran."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Otključajte telefon za još opcija"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Otključajte tablet za još opcija"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Otključajte uređaj za još opcija"</string>
diff --git a/packages/SystemUI/res-product/values-be/strings.xml b/packages/SystemUI/res-product/values-be/strings.xml
index cf42bedc54b9..78e41d67a0e2 100644
--- a/packages/SystemUI/res-product/values-be/strings.xml
+++ b/packages/SystemUI/res-product/values-be/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Працоўны профіль будзе выдалены, і гэта прывядзе да выдалення ўсіх даных у профілі."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Вы няправільна ўвялі ўзор разблакіроўкі столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) вам будзе прапанавана разблакіраваць планшэт, увайшоўшы ва ўліковы запіс электроннай пошты.\n\n Паўтарыце спробу праз <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Вы няправільна ўвялі ўзор разблакіроўкі столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) вам будзе прапанавана разблакіраваць тэлефон, увайшоўшы ва ўліковы запіс электроннай пошты.\n\n Паўтарыце спробу праз <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сканер адбіткаў пальцаў знаходзіцца на кнопцы сілкавання. Гэта плоская кнопка побач з выпуклай кнопкай гучнасці на бакавой грані планшэта.\n\nНацісканне кнопкі сілкавання выключае экран."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сканер адбіткаў пальцаў знаходзіцца на кнопцы сілкавання. Гэта плоская кнопка побач з выпуклай кнопкай гучнасці на бакавой грані прылады.\n\nНацісканне кнопкі сілкавання выключае экран."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сканер адбіткаў пальцаў знаходзіцца на кнопцы сілкавання. Гэта плоская кнопка побач з выпуклай кнопкай гучнасці на бакавой грані тэлефона.\n\nНацісканне кнопкі сілкавання выключае экран."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Каб адкрыць іншыя параметры, разблакіруйце тэлефон"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Каб адкрыць іншыя параметры, разблакіруйце планшэт"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Каб адкрыць іншыя параметры, разблакіруйце прыладу"</string>
diff --git a/packages/SystemUI/res-product/values-bg/strings.xml b/packages/SystemUI/res-product/values-bg/strings.xml
index 182ffa90f450..bd3a35403aae 100644
--- a/packages/SystemUI/res-product/values-bg/strings.xml
+++ b/packages/SystemUI/res-product/values-bg/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Служебният потребителски профил ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита ще бъдете помолени да отключите таблета си посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита ще бъдете помолени да отключите телефона посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сензорът за отпечатъци се намира върху бутона за захранване. Този бутон е плосък и е разположен на ръба на таблета до повдигнатия бутон за силата на звука.\n\nС натискането на бутона за захранване се изключва екранът."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сензорът за отпечатъци се намира върху бутона за захранване. Този бутон е плосък и е разположен на ръба на устройството до повдигнатия бутон за силата на звука.\n\nС натискането на бутона за захранване се изключва екранът."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сензорът за отпечатъци се намира върху бутона за захранване. Този бутон е плосък и е разположен на ръба на телефона до повдигнатия бутон за силата на звука.\n\nС натискането на бутона за захранване се изключва екранът."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Отключете телефона си за още опции"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Отключете таблета си за още опции"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Отключете устройството си за още опции"</string>
diff --git a/packages/SystemUI/res-product/values-bn/strings.xml b/packages/SystemUI/res-product/values-bn/strings.xml
index d54de525615b..58b646c0ec26 100644
--- a/packages/SystemUI/res-product/values-bn/strings.xml
+++ b/packages/SystemUI/res-product/values-bn/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুল পদ্ধতিতে ফোন আনলক করার চেষ্টা করেছেন। অফিস প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে প্যাটার্ন আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে আপনাকে প্যাটার্ন আনলক করতে একটি ইমেল অ্যাকাউন্ট ব্যবহার করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন।"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে প্যাটার্ন আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে আপনাকে প্যাটার্ন আনলক করতে একটি ইমেল অ্যাকাউন্ট ব্যবহারের করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"\'পাওয়ার\' বোতামের উপরে ফিঙ্গারপ্রিন্ট সেন্সর আছে। এটি ট্যাবলেটের প্রান্তে উঁচু \'ভলিউম\' বোতামের পাশে থাকা চ্যাপ্টা বোতাম।\n\n\'পাওয়ার\' বোতাম প্রেস করলে স্ক্রিন বন্ধ হয়ে যায়।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"\'পাওয়ার\' বোতামের উপরে ফিঙ্গারপ্রিন্ট সেন্সর আছে। এটি ডিভাইসের প্রান্তে উঁচু \'ভলিউম\' বোতামের পাশে থাকা চ্যাপ্টা বোতাম।\n\n\'পাওয়ার\' বোতাম প্রেস করলে স্ক্রিন বন্ধ হয়ে যায়।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"\'পাওয়ার\' বোতামের উপরে ফিঙ্গারপ্রিন্ট সেন্সর আছে। এটি ফোনের প্রান্তে উঁচু \'ভলিউম\' বোতামের পাশে থাকা চ্যাপ্টা বোতাম।\n\n\'পাওয়ার\' বোতাম প্রেস করলে স্ক্রিন বন্ধ হয়ে যায়।"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"আরও বিকল্প দেখতে আপনার ফোন আনলক করুন"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"আরও বিকল্প দেখতে আপনার ট্যাবলেট আনলক করুন"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"আরও বিকল্প দেখতে আপনার ডিভাইস আনলক করুন"</string>
diff --git a/packages/SystemUI/res-product/values-bs/strings.xml b/packages/SystemUI/res-product/values-bs/strings.xml
index 9567125f42f6..36c911fd4b37 100644
--- a/packages/SystemUI/res-product/values-bs/strings.xml
+++ b/packages/SystemUI/res-product/values-bs/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Pokušali ste neispravno otključati telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Radni profil će se ukloniti i svi podaci s profila će se izbrisati."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Pogrešno ste nacrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, od vas će se tražiti da otključate tablet pomoću računa e-pošte. \n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Pogrešno ste nacrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, od vas će se tražiti da otključate telefon pomoću računa e-pošte. \n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Senzor za otisak prsta je na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na rubu tableta.\n\nPritiskanjem dugmeta za uključivanje isključuje se ekran."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Senzor za otisak prsta je na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na rubu uređaja.\n\nPritiskanjem dugmeta za uključivanje isključuje se ekran."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Senzor za otisak prsta je na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na rubu telefona.\n\nPritiskanjem dugmeta za uključivanje isključuje se ekran."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Otključajte telefon za više opcija"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Otključajte tablet za više opcija"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Otključajte uređaj za više opcija"</string>
diff --git a/packages/SystemUI/res-product/values-ca/strings.xml b/packages/SystemUI/res-product/values-ca/strings.xml
index d318b4ef6275..be767e41bf83 100644
--- a/packages/SystemUI/res-product/values-ca/strings.xml
+++ b/packages/SystemUI/res-product/values-ca/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. El perfil de treball se suprimirà, juntament amb totes les dades que contingui."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis la tauleta amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis el telèfon amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"El sensor d\'empremtes digitals es troba al botó d\'engegada. És el botó pla situat al costat del botó de volum amb relleu al lateral de la tauleta.\n\nEn prémer el botó d\'engegada, la pantalla es desactiva."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"El sensor d\'empremtes digitals es troba al botó d\'engegada. És el botó pla situat al costat del botó de volum amb relleu al lateral del dispositiu.\n\nEn prémer el botó d\'engegada, la pantalla es desactiva."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"El sensor d\'empremtes digitals es troba al botó d\'engegada. És el botó pla situat al costat del botó de volum amb relleu al lateral del telèfon.\n\nEn prémer el botó d\'engegada, la pantalla es desactiva."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloqueja el teu telèfon per veure més opcions"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloqueja la teva tauleta per veure més opcions"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueja el teu dispositiu per veure més opcions"</string>
diff --git a/packages/SystemUI/res-product/values-cs/strings.xml b/packages/SystemUI/res-product/values-cs/strings.xml
index e1ee268b4eb7..e41154ba2e1e 100644
--- a/packages/SystemUI/res-product/values-cs/strings.xml
+++ b/packages/SystemUI/res-product/values-cs/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Již <xliff:g id="NUMBER">%d</xliff:g>krát jste se pokusili odemknout telefon nesprávným způsobem. Pracovní profil bude odstraněn, čímž budou smazána všechna jeho data."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně zadali své bezpečnostní gesto. Po <xliff:g id="NUMBER_1">%2$d</xliff:g>dalších neúspěšných pokusech budete požádáni o odemčení tabletu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně zadali své bezpečnostní gesto. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech budete požádáni o odemčení telefonu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Snímač otisků prstů je na vypínači. Je to ploché tlačítko vedle vystouplého tlačítka hlasitosti na hraně tabletu.\n\nStisknutím vypínače vypnete obrazovku."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Snímač otisků prstů je na vypínači. Je to ploché tlačítko vedle vystouplého tlačítka hlasitosti na hraně zařízení.\n\nStisknutím vypínače vypnete obrazovku."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Snímač otisků prstů je na vypínači. Je to ploché tlačítko vedle vystouplého tlačítka hlasitosti na hraně telefonu.\n\nStisknutím vypínače vypnete obrazovku."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Chcete-li zobrazit další možnosti, odemkněte telefon"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Chcete-li zobrazit další možnosti, odemkněte tablet"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Chcete-li zobrazit další možnosti, odemkněte zařízení"</string>
diff --git a/packages/SystemUI/res-product/values-da/strings.xml b/packages/SystemUI/res-product/values-da/strings.xml
index 55bda6992c87..c92217047e6f 100644
--- a/packages/SystemUI/res-product/values-da/strings.xml
+++ b/packages/SystemUI/res-product/values-da/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du har forsøgt at låse telefonen op med den forkerte adgangskode <xliff:g id="NUMBER">%d</xliff:g> gange. Arbejdsprofilen fjernes, hvilket sletter alle profildata."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din tablet op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din telefon op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Fingeraftrykssensoren sidder på afbryderknappen. Det er den flade knap ud for den hævede lydstyrkeknap på din tablets kant.\n\nNår du trykker på afbryderknappen, slukkes skærmen."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Fingeraftrykssensoren sidder på afbryderknappen. Det er den flade knap ud for den hævede lydstyrkeknap på enhedens kant.\n\nNår du trykker på afbryderknappen, slukkes skærmen."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Fingeraftrykssensoren sidder på afbryderknappen. Det er den flade knap ud for den hævede lydstyrkeknap på telefonens kant.\n\nNår du trykker på afbryderknappen, slukkes skærmen."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Lås din telefon op for at se flere valgmuligheder"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Lås din tablet op for at se flere valgmuligheder"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lås din enhed op for at se flere valgmuligheder"</string>
diff --git a/packages/SystemUI/res-product/values-de/strings.xml b/packages/SystemUI/res-product/values-de/strings.xml
index c82c7390e52e..2433f88e3242 100644
--- a/packages/SystemUI/res-product/values-de/strings.xml
+++ b/packages/SystemUI/res-product/values-de/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Smartphone zu entsperren. Das Arbeitsprofil wird nun entfernt und alle Profildaten werden gelöscht."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Tablet mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Smartphone mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Der Fingerabdrucksensor befindet sich auf der Ein-/Aus-Taste. Das ist die flache Taste neben der erhöhten Lautstärketaste an der Seite des Tablets.\n\nWenn du die Ein-/Aus-Taste drückst, schaltet sich das Display aus."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Der Fingerabdrucksensor befindet sich auf der Ein-/Aus-Taste. Das ist die flache Taste neben der erhöhten Lautstärketaste an der Seite des Geräts.\n\nWenn du die Ein-/Aus-Taste drückst, schaltet sich das Display aus."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Der Fingerabdrucksensor befindet sich auf der Ein-/Aus-Taste. Das ist die flache Taste neben der erhöhten Lautstärketaste an der Seite des Smartphones.\n\nWenn du die Ein-/Aus-Taste drückst, schaltet sich das Display aus."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Entsperre dein Smartphone für weitere Optionen"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Entsperre dein Tablet für weitere Optionen"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Entsperre dein Gerät für weitere Optionen"</string>
diff --git a/packages/SystemUI/res-product/values-el/strings.xml b/packages/SystemUI/res-product/values-el/strings.xml
index 3d38be49fad6..c1b8df507922 100644
--- a/packages/SystemUI/res-product/values-el/strings.xml
+++ b/packages/SystemUI/res-product/values-el/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Το προφίλ εργασίας θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα προφίλ."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, θα σας ζητηθεί να ξεκλειδώσετε το tablet με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε να συνδεθείτε ξανά σε <xliff:g id="NUMBER_2">%3$d</xliff:g> δευτερόλεπτα."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, θα σας ζητηθεί να ξεκλειδώσετε το τηλέφωνό σας με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε ξανά σε <xliff:g id="NUMBER_2">%3$d</xliff:g> δευτερόλεπτα."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Ο αισθητήρας δακτυλικών αποτυπωμάτων βρίσκεται στο κουμπί λειτουργίας. Είναι το επίπεδο κουμπί δίπλα στο ανυψωμένο κουμπί έντασης ήχου στο άκρο του tablet.\n\nΜε πάτημα του κουμπιού λειτουργίας απενεργοποιείται η οθόνη."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Ο αισθητήρας δακτυλικών αποτυπωμάτων βρίσκεται στο κουμπί λειτουργίας. Είναι το επίπεδο κουμπί δίπλα στο ανυψωμένο κουμπί έντασης ήχου στο άκρο της συσκευής.\n\nΜε πάτημα του κουμπιού λειτουργίας απενεργοποιείται η οθόνη."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Ο αισθητήρας δακτυλικών αποτυπωμάτων βρίσκεται στο κουμπί λειτουργίας. Είναι το επίπεδο κουμπί δίπλα στο ανυψωμένο κουμπί έντασης ήχου στο άκρο του τηλεφώνου.\n\nΜε πάτημα του κουμπιού λειτουργίας απενεργοποιείται η οθόνη."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Ξεκλειδώστε το τηλέφωνό σας για περισσότερες επιλογές"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Ξεκλειδώστε το tablet για περισσότερες επιλογές"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ξεκλειδώστε τη συσκευή σας για περισσότερες επιλογές"</string>
diff --git a/packages/SystemUI/res-product/values-en-rAU/strings.xml b/packages/SystemUI/res-product/values-en-rAU/strings.xml
index 04e63f5eb428..61d915a95a10 100644
--- a/packages/SystemUI/res-product/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rAU/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Unlock your phone for more options"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Unlock your tablet for more options"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
diff --git a/packages/SystemUI/res-product/values-en-rCA/strings.xml b/packages/SystemUI/res-product/values-en-rCA/strings.xml
index 131c42a700a3..f99aeae093a3 100644
--- a/packages/SystemUI/res-product/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rCA/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Unlock your phone for more options"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Unlock your tablet for more options"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
diff --git a/packages/SystemUI/res-product/values-en-rGB/strings.xml b/packages/SystemUI/res-product/values-en-rGB/strings.xml
index 04e63f5eb428..61d915a95a10 100644
--- a/packages/SystemUI/res-product/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rGB/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Unlock your phone for more options"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Unlock your tablet for more options"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
diff --git a/packages/SystemUI/res-product/values-en-rIN/strings.xml b/packages/SystemUI/res-product/values-en-rIN/strings.xml
index 04e63f5eb428..61d915a95a10 100644
--- a/packages/SystemUI/res-product/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rIN/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Unlock your phone for more options"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Unlock your tablet for more options"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
diff --git a/packages/SystemUI/res-product/values-en-rXC/strings.xml b/packages/SystemUI/res-product/values-en-rXC/strings.xml
index aa895e1364e2..32afc2f52745 100644
--- a/packages/SystemUI/res-product/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rXC/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. The work profile will be removed, which will delete all profile data.‎‏‎‎‏‎"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎‎‎‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, you will be asked to unlock your tablet using an email account.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, you will be asked to unlock your phone using an email account.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Pressing the power button turns off the screen.‎‏‎‎‏‎"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‎The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Pressing the power button turns off the screen.‎‏‎‎‏‎"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‏‎The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Pressing the power button turns off the screen.‎‏‎‎‏‎"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‏‎Unlock your phone for more options‎‏‎‎‏‎"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎Unlock your tablet for more options‎‏‎‎‏‎"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‎‎‎‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎Unlock your device for more options‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res-product/values-es-rUS/strings.xml b/packages/SystemUI/res-product/values-es-rUS/strings.xml
index 7e0eec601a7c..3014d2e21a95 100644
--- a/packages/SystemUI/res-product/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-product/values-es-rUS/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se quitará el perfil de trabajo, lo que borrará todos los datos asociados."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Dibujaste el patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees la tablet mediante una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Dibujaste el patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees el dispositivo mediante una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"El sensor de huellas dactilares está en el botón de encendido. Es el botón plano que está junto al botón de volumen en relieve, en el borde de la tablet.\n\nSi presionas el botón de encendido, se apaga la pantalla."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"El sensor de huellas dactilares está en el botón de encendido. Es el botón plano que está junto al botón de volumen en relieve, en el borde del dispositivo.\n\nSi presionas el botón de encendido, se apaga la pantalla."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"El sensor de huellas dactilares está en el botón de encendido. Es el botón plano que está junto al botón de volumen en relieve, en el borde del teléfono.\n\nSi presionas el botón de encendido, se apaga la pantalla."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloquea el teléfono para ver más opciones"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloquea la tablet para ver más opciones"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloquea el dispositivo para ver más opciones"</string>
diff --git a/packages/SystemUI/res-product/values-es/strings.xml b/packages/SystemUI/res-product/values-es/strings.xml
index 970c615bf5db..009ab56c6b2b 100644
--- a/packages/SystemUI/res-product/values-es/strings.xml
+++ b/packages/SystemUI/res-product/values-es/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Has intentado desbloquear el teléfono de forma incorrecta <xliff:g id="NUMBER">%d</xliff:g> veces. Se quitará este perfil de trabajo y se eliminarán todos sus datos."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Has dibujado un patrón de desbloqueo incorrecto <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te pedirá que desbloquees el tablet con una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Has dibujado un patrón de desbloqueo incorrecto <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te pedirá que desbloquees el teléfono con una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"El sensor de huellas digitales está en el botón de encendido. Es el botón plano situado junto al botón de volumen con relieve en el lateral del tablet.\n\nAl pulsar el botón de encendido, se apagará la pantalla."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"El sensor de huellas digitales está en el botón de encendido. Es el botón plano situado junto al botón de volumen con relieve en el lateral del dispositivo.\n\nAl pulsar el botón de encendido, se apagará la pantalla."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"El sensor de huellas digitales está en el botón de encendido. Es el botón plano situado junto al botón de volumen con relieve en el lateral del teléfono.\n\nAl pulsar el botón de encendido, se apagará la pantalla."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloquea el teléfono para ver más opciones"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloquea el tablet para ver más opciones"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloquea el dispositivo para ver más opciones"</string>
diff --git a/packages/SystemUI/res-product/values-et/strings.xml b/packages/SystemUI/res-product/values-et/strings.xml
index ae463f204d2e..e3165d3a7b9b 100644
--- a/packages/SystemUI/res-product/values-et/strings.xml
+++ b/packages/SystemUI/res-product/values-et/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda telefoni valesti avada. Tööprofiil eemaldatakse ja kõik profiiliandmed kustutatakse."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset palutakse teil tahvelarvuti avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundi pärast."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset palutakse teil telefon avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundi pärast."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Sõrmejäljeandur asub toitenupul. See on tahvelarvuti küljel helitugevuse kõrgendatud nupu kõrval olev lame nupp.\n\nToitenupu vajutamisel lülitatakse ekraan välja."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Sõrmejäljeandur asub toitenupul. See on seadme küljel helitugevuse kõrgendatud nupu kõrval olev lame nupp.\n\nToitenupu vajutamisel lülitatakse ekraan välja."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Sõrmejäljeandur asub toitenupul. See on telefoni küljel helitugevuse kõrgendatud nupu kõrval olev lame nupp.\n\nToitenupu vajutamisel lülitatakse ekraan välja."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Lisavalikute nägemiseks avage oma telefon"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Lisavalikute nägemiseks avage oma tahvelarvuti"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lisavalikute nägemiseks avage oma seade"</string>
diff --git a/packages/SystemUI/res-product/values-eu/strings.xml b/packages/SystemUI/res-product/values-eu/strings.xml
index 7cf68f643b4f..c7cf96bc17ba 100644
--- a/packages/SystemUI/res-product/values-eu/strings.xml
+++ b/packages/SystemUI/res-product/values-eu/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Laneko profila kendu egingo da eta, ondorioz, profileko datu guztiak ezabatuko dira."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz oker marrazten baduzu, tableta posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz oker marrazten baduzu, telefonoa posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Hatz-marken sentsorea etengailuan dago. Tabletaren ertzeko bolumen-botoi goratuaren ondoan dagoen botoi laua da.\n\nEtengailua sakatuz gero, pantaila itzaliko da."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Hatz-marken sentsorea etengailuan dago. Gailuaren ertzeko bolumen-botoi goratuaren ondoan dagoen botoi laua da.\n\nEtengailua sakatuz gero, pantaila itzaliko da."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Hatz-marken sentsorea etengailuan dago. Telefonoaren ertzeko bolumen-botoi goratuaren ondoan dagoen botoi laua da.\n\nEtengailua sakatuz gero, pantaila itzaliko da."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desblokeatu telefonoa aukera gehiago ikusteko"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desblokeatu tableta aukera gehiago ikusteko"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desblokeatu gailua aukera gehiago ikusteko"</string>
diff --git a/packages/SystemUI/res-product/values-fa/strings.xml b/packages/SystemUI/res-product/values-fa/strings.xml
index 5ff301158192..6ec1145ccffe 100644
--- a/packages/SystemUI/res-product/values-fa/strings.xml
+++ b/packages/SystemUI/res-product/values-fa/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. نمایه کاری پاک می‌شود که با آن همه داده‌های نمایه حذف می‌شود."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"‏الگوی بازگشایی قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. بعداز <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‌‎شود که بااستفاده از یک حساب ایمیل قفل رایانه لوحی‌تان را باز کنید.\n\n لطفاً پس‌از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"الگوی بازگشایی قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. پس‌از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‌شود که بااستفاده از یک حساب ایمیل قفل تلفن را باز کنید.\n\n لطفاً پس‌از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"حسگر اثر انگشت روی دکمه روشن/خاموش قرار دارد. این همان دکمه مسطحی است که کنار دکمه برآمده صدا در لبه رایانه لوحی قرار دارد.\n\nفشار دادن دکمه روشن/خاموش، صفحه‌نمایش را خاموش می‌کند."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"حسگر اثر انگشت روی دکمه روشن/خاموش قرار دارد. این همان دکمه مسطحی است که کنار دکمه برآمده صدا در لبه دستگاه قرار دارد.\n\nفشار دادن دکمه روشن/خاموش، صفحه‌نمایش را خاموش می‌کند."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"حسگر اثر انگشت روی دکمه روشن/خاموش قرار دارد. این همان دکمه مسطحی است که کنار دکمه برآمده صدا در لبه تلفن قرار دارد.\n\nفشار دادن دکمه روشن/خاموش، صفحه‌نمایش را خاموش می‌کند."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"برای گزینه‌های بیشتر، قفل تلفن را باز کنید"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"برای گزینه‌های بیشتر، قفل رایانه لوحی را باز کنید"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"برای گزینه‌های بیشتر، قفل دستگاه را باز کنید"</string>
diff --git a/packages/SystemUI/res-product/values-fi/strings.xml b/packages/SystemUI/res-product/values-fi/strings.xml
index 55a65ea687af..52c4ffc26700 100644
--- a/packages/SystemUI/res-product/values-fi/strings.xml
+++ b/packages/SystemUI/res-product/values-fi/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Työprofiili ja kaikki sen data poistetaan."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%2$d</xliff:g> kertaa, sinua pyydetään avaamaan tabletin lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunnin kuluttua."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%2$d</xliff:g> kertaa, sinua pyydetään avaamaan puhelimesi lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunnin kuluttua."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Sormenjälkitunnistin on virtapainikkeessa. Se on litteä painike koholla olevan äänenvoimakkuuspainikkeen vieressä tabletin sivussa.\n\nJos painat virtapainiketta, näyttö sammuu."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Sormenjälkitunnistin on virtapainikkeessa. Se on litteä painike koholla olevan äänenvoimakkuuspainikkeen vieressä laitteen sivussa.\n\nJos painat virtapainiketta, näyttö sammuu."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Sormenjälkitunnistin on virtapainikkeessa. Se on litteä painike koholla olevan äänenvoimakkuuspainikkeen vieressä puhelimen sivussa.\n\nJos painat virtapainiketta, näyttö sammuu."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Avaa puhelimen lukitus, niin näet enemmän vaihtoehtoja"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Avaa tabletin lukitus, niin näet enemmän vaihtoehtoja"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Avaa laitteen lukitus, niin näet enemmän vaihtoehtoja"</string>
diff --git a/packages/SystemUI/res-product/values-fr-rCA/strings.xml b/packages/SystemUI/res-product/values-fr-rCA/strings.xml
index 1ffa04231f8c..38acf15a6e68 100644
--- a/packages/SystemUI/res-product/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-product/values-fr-rCA/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel sera supprimé, ce qui entraîne la suppression de toutes ses données."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de courriel.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de courriel.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Le capteur d\'empreintes digitales est situé sur l\'interrupteur. Il s\'agit du bouton plat situé à côté du bouton de volume surélevé, sur le bord de la tablette.\n\nEn appuyant sur l\'interrupteur, vous éteignez l\'écran."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Le capteur d\'empreintes digitales est situé sur l\'interrupteur. Il s\'agit du bouton plat situé à côté du bouton de volume surélevé, sur le bord de l\'appareil.\n\nEn appuyant sur l\'interrupteur, vous éteignez l\'écran."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Le capteur d\'empreintes digitales est situé sur l\'interrupteur. Il s\'agit du bouton plat situé à côté du bouton de volume surélevé, sur le bord du téléphone.\n\nEn appuyant sur l\'interrupteur, vous éteignez l\'écran."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Déverrouillez votre téléphone pour afficher davantage d\'options"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Déverrouillez votre tablette pour afficher davantage d\'options"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Déverrouillez votre appareil pour afficher davantage d\'options"</string>
diff --git a/packages/SystemUI/res-product/values-fr/strings.xml b/packages/SystemUI/res-product/values-fr/strings.xml
index 75a08628522b..faeeaa62731c 100644
--- a/packages/SystemUI/res-product/values-fr/strings.xml
+++ b/packages/SystemUI/res-product/values-fr/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel et toutes les données associées vont être supprimés."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de messagerie électronique.\n\nRéessayez dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\nRéessayez dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Le lecteur d\'empreinte digitale se trouve sur le bouton Marche/Arrêt. C\'est le bouton plat à côté du bouton de volume en relief sur un bord de la tablette.\n\nAppuyer sur le bouton Marche/Arrêt éteint l\'écran."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Le lecteur d\'empreinte digitale se trouve sur le bouton Marche/Arrêt. C\'est le bouton plat à côté du bouton de volume en relief sur un bord de l\'appareil.\n\nAppuyer sur le bouton Marche/Arrêt éteint l\'écran."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Le lecteur d\'empreinte digitale se trouve sur le bouton Marche/Arrêt. C\'est le bouton plat à côté du bouton de volume en relief sur un bord du téléphone.\n\nAppuyer sur le bouton Marche/Arrêt éteint l\'écran."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Déverrouillez votre téléphone pour obtenir plus d\'options"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Déverrouillez votre tablette pour obtenir plus d\'options"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Déverrouillez votre appareil pour obtenir plus d\'options"</string>
diff --git a/packages/SystemUI/res-product/values-gl/strings.xml b/packages/SystemUI/res-product/values-gl/strings.xml
index 25fbb250e2d0..8e89c79190ef 100644
--- a/packages/SystemUI/res-product/values-gl/strings.xml
+++ b/packages/SystemUI/res-product/values-gl/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Quitarase o perfil de traballo e, por conseguinte, todos os seus datos."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Debuxaches o padrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, terás que desbloquear a tableta a través dunha conta de correo electrónico.\n\n Téntao de novo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Debuxaches o padrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, terás que desbloquear o teléfono a través dunha conta de correo electrónico.\n\n Téntao de novo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"O sensor de impresión dixital está no botón de acendido. É o botón plano que está ao lado do botón de volume con relevo, no lateral da tableta.\n\nAo premer o botón de acendido, apágase a pantalla."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"O sensor de impresión dixital está no botón de acendido. É o botón plano que está ao lado do botón de volume con relevo, no lateral do dispositivo.\n\nAo premer o botón de acendido, apágase a pantalla."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"O sensor de impresión dixital está no botón de acendido. É o botón plano que está ao lado do botón de volume con relevo, no lateral do teléfono.\n\nAo premer o botón de acendido, apágase a pantalla."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloquea o teléfono para ver máis opcións"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloquea a tableta para ver máis opcións"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloquea o dispositivo para ver máis opcións"</string>
diff --git a/packages/SystemUI/res-product/values-gu/strings.xml b/packages/SystemUI/res-product/values-gu/strings.xml
index b889dccd4ad3..42449e2ef16b 100644
--- a/packages/SystemUI/res-product/values-gu/strings.xml
+++ b/packages/SystemUI/res-product/values-gu/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"તમે ફોનને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ કાર્યાલયની પ્રોફાઇલ કાઢી નાખવામાં આવશે, જે તમામ પ્રોફાઇલ ડેટાને ડિલીટ કરી દેશે."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"તમે તમારી અનલૉક પૅટર્ન <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, તમને એક ઇમેઇલ એકાઉન્ટનો ઉપયોગ કરીને તમારા ટૅબ્લેટને અનલૉક કરવાનું કહેવામાં આવશે.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> સેકન્ડમાં ફરી પ્રયાસ કરો."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"તમે તમારી અનલૉક પૅટર્ન <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, તમને ઇમેઇલ એકાઉન્ટનો ઉપયોગ કરીને તમારા ફોનને અનલૉક કરવાનું કહેવામાં આવશે.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ફિંગરપ્રિન્ટ સેન્સર પાવર બટન પર છે. તે ટૅબ્લેટની કિનારીએ આવેલા ઉપસેલા વૉલ્યૂમ બટનની બાજુમાં આવેલું સપાટ બટન છે.\n\nપાવર બટન દબાવવાથી સ્ક્રીન બંધ થાય છે."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ફિંગરપ્રિન્ટ સેન્સર પાવર બટન પર છે. તે ડિવાઇસની કિનારીએ આવેલા ઉપસેલા વૉલ્યૂમ બટનની બાજુમાં આવેલું સપાટ બટન છે.\n\nપાવર બટન દબાવવાથી સ્ક્રીન બંધ થાય છે."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ફિંગરપ્રિન્ટ સેન્સર પાવર બટન પર છે. તે ફોનની કિનારીએ આવેલા ઉપસેલા વૉલ્યૂમ બટનની બાજુમાં આવેલું સપાટ બટન છે.\n\nપાવર બટન દબાવવાથી સ્ક્રીન બંધ થાય છે."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"વધુ વિકલ્પો માટે તમારા ફોનને અનલૉક કરો"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"વધુ વિકલ્પો માટે તમારા ટૅબ્લેટને અનલૉક કરો"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"વધુ વિકલ્પો માટે તમારા ડિવાઇસને અનલૉક કરો"</string>
diff --git a/packages/SystemUI/res-product/values-hi/strings.xml b/packages/SystemUI/res-product/values-hi/strings.xml
index f148fc56bb61..f6f17a094dff 100644
--- a/packages/SystemUI/res-product/values-hi/strings.xml
+++ b/packages/SystemUI/res-product/values-hi/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इसकी वजह से वर्क प्रोफ़ाइल को हटा दिया जाएगा जिससे उपयोगकर्ता की प्रोफ़ाइल का सारा डेटा मिट जाएगा."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"आपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से बनाया है. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पैटर्न बनाने के बाद, टैबलेट को अनलॉक करने के लिए आपसे ईमेल खाते का इस्तेमाल करने को कहा जाएगा.\n\n अनलॉक करने के लिए <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"आपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से बनाया है. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पैटर्न बनाने के बाद, आपसे फ़ोन को अनलॉक करने के लिए ईमेल खाते का इस्तेमाल करने को कहा जाएगा.\n\n अनलॉक करने के लिए <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"फ़िंगरप्रिंट सेंसर, पावर बटन पर होता है. यह टैबलेट के किनारे पर मौजूद एक फ़्लैट बटन होता है, जो कि आपको आवाज़ कम या ज़्यादा करने वाले उभरे हुए बटन के नीचे मिलेगा.\n\nपावर बटन दबाने से स्क्रीन बंद हो जाती है."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"फ़िंगरप्रिंट सेंसर, पावर बटन पर होता है. यह डिवाइस के किनारे पर मौजूद एक फ़्लैट बटन होता है, जो कि आपको आवाज़ कम या ज़्यादा करने वाले उभरे हुए बटन के नीचे मिलेगा.\n\nपावर बटन दबाने से स्क्रीन बंद हो जाती है."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"फ़िंगरप्रिंट सेंसर, पावर बटन पर होता है. यह फ़ोन के किनारे पर मौजूद एक फ़्लैट बटन होता है, जो कि आपको आवाज़ कम या ज़्यादा करने वाले उभरे हुए बटन के नीचे मिलेगा.\n\nपावर बटन दबाने से स्क्रीन बंद हो जाती है."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ज़्यादा विकल्प देखने के लिए, अपना फ़ोन अनलॉक करें"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ज़्यादा विकल्प देखने के लिए, अपना टैबलेट अनलॉक करें"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ज़्यादा विकल्प देखने के लिए, अपना डिवाइस अनलॉक करें"</string>
diff --git a/packages/SystemUI/res-product/values-hr/strings.xml b/packages/SystemUI/res-product/values-hr/strings.xml
index 73ffd6224c60..6ea4a48adaaf 100644
--- a/packages/SystemUI/res-product/values-hr/strings.xml
+++ b/packages/SystemUI/res-product/values-hr/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER">%d</xliff:g> put/a. Radni će se profil ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja morat ćete otključati tablet pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja morat ćete otključati telefon pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Senzor otiska prsta nalazi se na tipki za uključivanje/isključivanje. To je ravni gumb pored izdignutog gumba za glasnoću na rubu tableta.\n\nPritiskom na tipku za uključivanje/isključivanje isključuje se zaslon."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Senzor otiska prsta nalazi se na tipki za uključivanje/isključivanje. To je ravni gumb pored izdignutog gumba za glasnoću na rubu uređaja.\n\nPritiskom na tipku za uključivanje/isključivanje isključuje se zaslon."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Senzor otiska prsta nalazi se na tipki za uključivanje/isključivanje. To je ravni gumb pored izdignutog gumba za glasnoću na rubu telefona.\n\nPritiskom na tipku za uključivanje/isključivanje isključuje se zaslon."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Za više opcija otključajte telefon"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Za više opcija otključajte tablet"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Za više opcija otključajte uređaj"</string>
diff --git a/packages/SystemUI/res-product/values-hu/strings.xml b/packages/SystemUI/res-product/values-hu/strings.xml
index 19d79d3dadbd..493c04cc9bd9 100644
--- a/packages/SystemUI/res-product/values-hu/strings.xml
+++ b/packages/SystemUI/res-product/values-hu/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. A rendszer eltávolítja a munkaprofilt, és ezzel a profil összes adata törlődik."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után e-mail-fiók használatával kell feloldania táblagépét.\n\nPróbálja újra <xliff:g id="NUMBER_2">%3$d</xliff:g> másodperc múlva."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után e-mail-fiók használatával kell feloldania telefonját.\n\nPróbálja újra <xliff:g id="NUMBER_2">%3$d</xliff:g> másodperc múlva."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Az ujjlenyomat-érzékelő a bekapcsológombon található. A kiemelkedő hangerőgomb melletti lapos gomb a táblagép szélén.\n\nA bekapcsológomb lenyomásával kikapcsol a képernyő."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Az ujjlenyomat-érzékelő a bekapcsológombon található. A kiemelkedő hangerőgomb melletti lapos gomb az eszköz szélén.\n\nA bekapcsológomb lenyomásával kikapcsol a képernyő."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Az ujjlenyomat-érzékelő a bekapcsológombon található. A kiemelkedő hangerőgomb melletti lapos gomb a telefon szélén.\n\nA bekapcsológomb lenyomásával kikapcsol a képernyő."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"További lehetőségekért oldja fel a telefont"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"További lehetőségekért oldja fel a táblagépet"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"További lehetőségekért oldja fel az eszközt"</string>
diff --git a/packages/SystemUI/res-product/values-hy/strings.xml b/packages/SystemUI/res-product/values-hy/strings.xml
index 17f42a0340da..81bcc74de501 100644
--- a/packages/SystemUI/res-product/values-hy/strings.xml
+++ b/packages/SystemUI/res-product/values-hy/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Աշխատանքային պրոֆիլը կհեռացվի, և պրոֆիլի բոլոր տվյալները կջնջվեն:"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Դուք կատարել եք ապակողպման նախշը մուտքագրելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո ձեզանից կպահանջվի ապակողպել պլանշետը էլփոստի հաշվի միջոցով։\n\n Խնդրում ենք կրկին փորձել <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ եք հավաքել ձեր ապակողպման նմուշը: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո ձեզ կառաջարկվի ապակողպել հեռախոսը` օգտագործելով էլփոստի հաշիվ:\n\n Կրկին փորձեք <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Մատնահետքերի սկաները սնուցման կոճակի վրա է։ Այն հարթ կոճակն է՝ ձայնի ուժգնության ուռուցիկ կոճակի կողքին, պլանշետի եզրային մասում։\n\nՍնուցման կոճակի սեղմումով էկրանն անջատվում է։"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Մատնահետքերի սկաները սնուցման կոճակի վրա է։ Այն հարթ կոճակն է՝ ձայնի ուժգնության ուռուցիկ կոճակի կողքին, սարքի եզրային մասում։\n\nՍնուցման կոճակի սեղմումով էկրանն անջատվում է։"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Մատնահետքերի սկաները սնուցման կոճակի վրա է։ Այն հարթ կոճակ է՝ ձայնի ուժգնության ուռուցիկ կոճակի կողքին, հեռախոսի եզրային մասում։\n\nՍնուցման կոճակի սեղմումով էկրանն անջատվում է։"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Ապակողպեք ձեր հեռախոսը՝ լրացուցիչ կարգավորումները տեսնելու համար"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Ապակողպեք ձեր պլանշետը՝ լրացուցիչ կարգավորումները տեսնելու համար"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ապակողպեք ձեր սարքը՝ լրացուցիչ կարգավորումները տեսնելու համար"</string>
diff --git a/packages/SystemUI/res-product/values-in/strings.xml b/packages/SystemUI/res-product/values-in/strings.xml
index 15d8f397c393..cef30a5cc95e 100644
--- a/packages/SystemUI/res-product/values-in/strings.xml
+++ b/packages/SystemUI/res-product/values-in/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Profil kerja akan dihapus, sehingga semua data profil akan dihapus."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, Anda akan diminta membuka kunci tablet menggunakan akun email.\n\n Coba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> detik."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, Anda akan diminta membuka kunci ponsel menggunakan akun email.\n\n Coba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> detik."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Sensor sidik jari ada di tombol daya. Tombol ini berupa tombol datar di samping tombol volume timbul di tepi tablet.\n\nMenekan tombol daya akan menonaktifkan layar."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Sensor sidik jari ada di tombol daya. Tombol ini berupa tombol datar di samping tombol volume timbul di tepi perangkat.\n\nMenekan tombol daya akan menonaktifkan layar."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Sensor sidik jari ada di tombol daya. Tombol ini berupa tombol datar di samping tombol volume timbul di tepi ponsel.\n\nMenekan tombol daya akan menonaktifkan layar."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Buka kunci ponsel untuk melihat opsi lainnya"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Buka kunci tablet untuk melihat opsi lainnya"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Buka kunci perangkat untuk melihat opsi lainnya"</string>
diff --git a/packages/SystemUI/res-product/values-is/strings.xml b/packages/SystemUI/res-product/values-is/strings.xml
index b24871c72238..c42616f30b8a 100644
--- a/packages/SystemUI/res-product/values-is/strings.xml
+++ b/packages/SystemUI/res-product/values-is/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna símann. Vinnusniðið verður fjarlægt, með þeim afleiðingum að öllum gögnum þess verður eytt."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verðurðu beðin(n) um að opna spjaldtölvuna með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%3$d</xliff:g> sekúndur."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verðurðu beðin(n) um að opna símann með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%3$d</xliff:g> sekúndur."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Fingrafaralesarinn er á aflrofanum. Það er flati hnappurinn við hliðina á upphleypta hljóðstyrkshnappnum á hlið spjaldtölvunnar.\n\nÞegar ýtt er á aflrofann slokknar á skjánum."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Fingrafaralesarinn er á aflrofanum. Það er flati hnappurinn við hliðina á upphleypta hljóðstyrkshnappnum á hlið tækisins.\n\nÞegar ýtt er á aflrofann slokknar á skjánum."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Fingrafaralesarinn er á aflrofanum. Það er flati hnappurinn við hliðina á upphleypta hljóðstyrkshnappnum á hlið símans.\n\nÞegar ýtt er á aflrofann slokknar á skjánum."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Taktu símann úr lás til að fá fleiri valkosti"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Taktu spjaldtölvuna úr lás til að fá fleiri valkosti"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Taktu tækið úr lás til að fá fleiri valkosti"</string>
diff --git a/packages/SystemUI/res-product/values-it/strings.xml b/packages/SystemUI/res-product/values-it/strings.xml
index 8e9875d8e5a8..4ebcb9850f14 100644
--- a/packages/SystemUI/res-product/values-it/strings.xml
+++ b/packages/SystemUI/res-product/values-it/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Il profilo di lavoro verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il tablet con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%3$d</xliff:g> secondi."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il telefono con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%3$d</xliff:g> secondi."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Il sensore di impronte digitali si trova sul tasto di accensione. Si tratta del tasto piatto accanto al tasto del volume in rilievo sulla parte laterale del tablet.\n\nSe premi il tasto di accensione viene disattivato lo schermo."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Il sensore di impronte digitali si trova sul tasto di accensione. Si tratta del tasto piatto accanto al tasto del volume in rilievo sulla parte laterale del dispositivo.\n\nSe premi il tasto di accensione viene disattivato lo schermo."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Il sensore di impronte digitali si trova sul tasto di accensione. Si tratta del tasto piatto accanto al tasto del volume in rilievo sulla parte laterale del telefono.\n\nSe premi il tasto di accensione viene disattivato lo schermo."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Sblocca il telefono per visualizzare altre opzioni"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Sblocca il tablet per visualizzare altre opzioni"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Sblocca il dispositivo per visualizzare altre opzioni"</string>
diff --git a/packages/SystemUI/res-product/values-iw/strings.xml b/packages/SystemUI/res-product/values-iw/strings.xml
index b3aa02819963..38c49b785e99 100644
--- a/packages/SystemUI/res-product/values-iw/strings.xml
+++ b/packages/SystemUI/res-product/values-iw/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER">%d</xliff:g> פעמים. פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, ,תישלח אליך בקשה לבטל את נעילת הטאבלט באמצעות חשבון אימייל‏.\n\n יש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תישלח אליך בקשה לבטל את נעילת הטלפון באמצעות חשבון אימייל‏.\n\n יש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"חיישן טביעת האצבע נמצא על לחצן ההפעלה. זה הלחצן השטוח ליד הלחצן הבולט של עוצמת הקול בפינת הטאבלט.\n\nלחיצה על לחצן ההפעלה מכבה את המסך."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"חיישן טביעת האצבע נמצא על לחצן ההפעלה. זה הלחצן השטוח ליד הלחצן הבולט של עוצמת הקול בפינת המכשיר.\n\nלחיצה על לחצן ההפעלה מכבה את המסך."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"חיישן טביעת האצבע נמצא על לחצן ההפעלה. זה הלחצן השטוח ליד הלחצן הבולט של עוצמת הקול בפינת הטלפון.\n\nלחיצה על לחצן ההפעלה מכבה את המסך."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"לאפשרויות נוספות, יש לבטל את נעילת הטלפון"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"לאפשרויות נוספות, יש לבטל את נעילת הטאבלט"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"לאפשרויות נוספות, יש לבטל את נעילת המכשיר"</string>
diff --git a/packages/SystemUI/res-product/values-ja/strings.xml b/packages/SystemUI/res-product/values-ja/strings.xml
index c51a04c93bbe..7f25430490eb 100644
--- a/packages/SystemUI/res-product/values-ja/strings.xml
+++ b/packages/SystemUI/res-product/values-ja/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"スマートフォンのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。仕事用プロファイルは削除され、プロファイルのデータはすべて消去されます。"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ロック解除パターンの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回間違えると、タブレットのロック解除にメール アカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後にもう一度お試しください。"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ロック解除パターンの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回間違えると、スマートフォンのロック解除にメール アカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後にもう一度お試しください。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"指紋認証センサーは電源ボタンに内蔵されています。タブレットの端にある盛り上がった音量ボタンの横のフラットなボタンです。\n\n電源ボタンを押すと画面が OFF になります。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"指紋認証センサーは電源ボタンに内蔵されています。デバイスの端にある盛り上がった音量ボタンの横のフラットなボタンです。\n\n電源ボタンを押すと画面が OFF になります。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"指紋認証センサーは電源ボタンに内蔵されています。スマートフォンの端にある盛り上がった音量ボタンの横のフラットなボタンです。\n\n電源ボタンを押すと画面が OFF になります。"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"スマートフォンのロックを解除してその他のオプションを表示する"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"タブレットのロックを解除してその他のオプションを表示する"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"デバイスのロックを解除してその他のオプションを表示する"</string>
diff --git a/packages/SystemUI/res-product/values-ka/strings.xml b/packages/SystemUI/res-product/values-ka/strings.xml
index 3474a7f8f67e..b9e0881c6e29 100644
--- a/packages/SystemUI/res-product/values-ka/strings.xml
+++ b/packages/SystemUI/res-product/values-ka/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, სამსახურის პროფილი ამოიშლება, რაც პროფილის ყველა მონაცემის წაშლას გამოიწვევს."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ მოგთხოვთ, ტაბლეტი თქვენი ელფოსტის ანგარიშის მეშვეობით განბლოკოთ.\n\n ცადეთ ხელახლა <xliff:g id="NUMBER_2">%3$d</xliff:g> წამში."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ მოგთხოვთ, ტელეფონი თქვენი ელფოსტის ანგარიშის მეშვეობით განბლოკოთ.\n\n ცადეთ ხელახლა <xliff:g id="NUMBER_2">%3$d</xliff:g> წამში."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"თითის ანაბეჭდის სენსორი ჩართვის ღილაკზეა. ეს არის ბრტყელი ღილაკი ხმის აწევის ღილაკის გვერდით ტაბლეტის კიდეზე.\n\nჩართვის ღილაკზე დაწკაპუნება გამორთავს ეკრანს."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"თითის ანაბეჭდის სენსორი ჩართვის ღილაკზეა. ეს არის ბრტყელი ღილაკი ხმის აწევის ღილაკის გვერდით მოწყობილობის კიდეზე.\n\nჩართვის ღილაკზე დაწკაპუნება გამორთავს ეკრანს."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"თითის ანაბეჭდის სენსორი ჩართვის ღილაკზეა. ეს არის ბრტყელი ღილაკი ხმის აწევის ღილაკის გვერდით ტელეფონის კიდეზე.\n\nჩართვის ღილაკზე დაწკაპუნება გამორთავს ეკრანს."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი ტელეფონი"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი ტაბლეტი"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი მოწყობილობა"</string>
diff --git a/packages/SystemUI/res-product/values-kk/strings.xml b/packages/SystemUI/res-product/values-kk/strings.xml
index 8cfda7efdec6..3f9deb451bcd 100644
--- a/packages/SystemUI/res-product/values-kk/strings.xml
+++ b/packages/SystemUI/res-product/values-kk/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефон құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін планшетті аккаунт арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін телефонды аккаунт арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Саусақ ізін оқу сканері қуат түймесінде орналасқан. Ол – планшеттің шетіндегі шығыңқы дыбыс деңгейі түймесінің жанында орналасқан жалпақ түйме.\n\nҚуат түймесі басылса, экран өшеді."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Саусақ ізін оқу сканері қуат түймесінде орналасқан. Ол – құрылғының шетіндегі шығыңқы дыбыс деңгейі түймесінің жанында орналасқан жалпақ түйме.\n\nҚуат түймесі басылса, экран өшеді."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Саусақ ізін оқу сканері қуат түймесінде орналасқан. Ол – телефонның шетіндегі шығыңқы дыбыс деңгейі түймесінің жанында орналасқан жалпақ түйме.\n\nҚуат түймесі басылса, экран өшеді."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Басқа опцияларды көру үшін телефон құлпын ашыңыз."</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Басқа опцияларды көру үшін планшет құлпын ашыңыз."</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Басқа опцияларды көру үшін құрылғы құлпын ашыңыз."</string>
diff --git a/packages/SystemUI/res-product/values-km/strings.xml b/packages/SystemUI/res-product/values-km/strings.xml
index 035432dea614..76336da37910 100644
--- a/packages/SystemUI/res-product/values-km/strings.xml
+++ b/packages/SystemUI/res-product/values-km/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដង​ហើយ។ កម្រង​ព័ត៌មាន​ការងារ​នេះ​នឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​កម្រង​ព័ត៌មាន​ទាំងអស់។"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"អ្នក​បាន​គូរ​លំនាំ​ដោះ​សោ​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ បន្ទាប់ពីមានការ​ព្យាយាម​ដោះ​សោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យ អ្នក​នឹង​ត្រូវ​បាន​ស្នើ​ឱ្យ​ដោះ​សោ​ថេប្លេត​របស់​អ្នក​ ដោយ​ប្រើ​គណនី​អ៊ីមែល។\n\n សូមព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_2">%3$d</xliff:g> វិនាទី​ទៀត។"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"អ្នកបានគូរលំនាំ​ដោះសោ​របស់អ្នក​មិន​ត្រឹមត្រូវចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដងហើយ។ បន្ទាប់ពីមាន​ការព្យាយាម​ដោះសោចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀតមិនទទួលបាន​ជោគជ័យ អ្នកនឹង​ត្រូវបាន​ស្នើឱ្យ​ដោះសោ​ទូរសព្ទ​របស់​អ្នកដោយ​ប្រើគណនី​អ៊ីមែល។\n\n សូមព្យាយាម​ម្ដងទៀតក្នុង​រយៈពេល <xliff:g id="NUMBER_2">%3$d</xliff:g> វិនាទីទៀត។"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"សេនស័រចាប់ស្នាមម្រាមដៃ​ស្ថិតនៅលើប៊ូតុង​ថាមពល។ វាជាប៊ូតុងរាបស្មើ​នៅ​ជាប់​នឹង​ប៊ូតុង​កម្រិត​សំឡេង​ដែល​លៀន​ចេញ​មក​នៅ​លើ​គែម​ថេប្លេត។\n\nការចុច​ប៊ូតុង​ថាមពល​នឹង​បិទ​អេក្រង់។"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"សេនស័រចាប់ស្នាមម្រាមដៃ​ស្ថិតនៅលើប៊ូតុង​ថាមពល។ វាជាប៊ូតុងរាបស្មើ​នៅ​ជាប់​នឹង​ប៊ូតុង​កម្រិត​សំឡេង​ដែល​លៀន​ចេញ​មក​នៅ​លើ​គែម​ឧបករណ៍។\n\nការចុច​ប៊ូតុង​ថាមពល​នឹង​បិទ​អេក្រង់។"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"សេនស័រចាប់ស្នាមម្រាមដៃ​ស្ថិតនៅលើប៊ូតុង​ថាមពល។ វាជាប៊ូតុងរាបស្មើ​នៅ​ជាប់​នឹង​ប៊ូតុង​កម្រិត​សំឡេង​ដែល​លៀន​ចេញ​មក​នៅ​លើ​គែម​ទូរសព្ទ។\n\nការចុច​ប៊ូតុង​ថាមពល​នឹង​បិទ​អេក្រង់។"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ដោះសោ​ទូរសព្ទរបស់អ្នក​សម្រាប់​ជម្រើសច្រើនទៀត"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ដោះសោ​ថេប្លេតរបស់អ្នក​សម្រាប់​ជម្រើសច្រើនទៀត"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ដោះសោ​ឧបករណ៍របស់អ្នក​សម្រាប់​ជម្រើសច្រើនទៀត"</string>
diff --git a/packages/SystemUI/res-product/values-kn/strings.xml b/packages/SystemUI/res-product/values-kn/strings.xml
index d795cefa4d24..5c6f329ee617 100644
--- a/packages/SystemUI/res-product/values-kn/strings.xml
+++ b/packages/SystemUI/res-product/values-kn/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಪ್ರೊಫೈಲ್‌ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಡ್ರಾ ಮಾಡಿರುವಿರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ನಿಮ್ಮ ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನಿಮ್ಮನ್ನು ಕೇಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಡ್ರಾ ಮಾಡಿರುವಿರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿ ನಿಮ್ಮ ಫೋನ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನಿಮ್ಮನ್ನು ಕೇಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಪವರ್ ಬಟನ್‌ನಲ್ಲಿದೆ. ಇದು ಟ್ಯಾಬ್ಲೆಟ್‌ನ ಅಂಚಿನಲ್ಲಿರುವ ಎತ್ತರಿಸಿದ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ನ ಪಕ್ಕದಲ್ಲಿರುವ ಚಪ್ಪಟೆ ಬಟನ್ ಆಗಿದೆ.\n\nಪವರ್ ಬಟನ್ ಅನ್ನು ಒತ್ತುವುದರಿಂದ ಸ್ಕ್ರೀನ್ ಆಫ್ ಆಗುತ್ತದೆ."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಪವರ್ ಬಟನ್‌ನಲ್ಲಿದೆ. ಇದು ಸಾಧನದ ಅಂಚಿನಲ್ಲಿರುವ ಎತ್ತರಿಸಿದ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ನ ಪಕ್ಕದಲ್ಲಿರುವ ಚಪ್ಪಟೆ ಬಟನ್ ಆಗಿದೆ.\n\nಪವರ್ ಬಟನ್ ಅನ್ನು ಒತ್ತುವುದರಿಂದ ಸ್ಕ್ರೀನ್ ಆಫ್ ಆಗುತ್ತದೆ."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಪವರ್ ಬಟನ್‌ನಲ್ಲಿದೆ. ಇದು ಫೋನ್ ಅಂಚಿನಲ್ಲಿರುವ ಎತ್ತರಿಸಿದ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ನ ಪಕ್ಕದಲ್ಲಿರುವ ಚಪ್ಪಟೆ ಬಟನ್ ಆಗಿದೆ.\n\nಪವರ್ ಬಟನ್ ಅನ್ನು ಒತ್ತುವುದರಿಂದ ಸ್ಕ್ರೀನ್ ಆಫ್ ಆಗುತ್ತದೆ."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
diff --git a/packages/SystemUI/res-product/values-ko/strings.xml b/packages/SystemUI/res-product/values-ko/strings.xml
index 651662f77e48..76d022ab68bb 100644
--- a/packages/SystemUI/res-product/values-ko/strings.xml
+++ b/packages/SystemUI/res-product/values-ko/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"휴대전화 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 직장 프로필과 모든 프로필 데이터가 삭제됩니다."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"잠금 해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 태블릿을 잠금 해제해야 합니다.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g>초 후에 다시 시도해 주세요."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"잠금 해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 휴대전화를 잠금 해제해야 합니다.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g>초 후에 다시 시도해 주세요."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"지문 센서는 전원 버튼에 있습니다. 태블릿 옆면의 튀어나온 볼륨 버튼 옆에 있는 평평한 버튼입니다.\n\n전원 버튼을 누르면 화면이 꺼집니다."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"지문 센서는 전원 버튼에 있습니다. 기기 옆면의 튀어나온 볼륨 버튼 옆에 있는 평평한 버튼입니다.\n\n전원 버튼을 누르면 화면이 꺼집니다."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"지문 센서는 전원 버튼에 있습니다. 휴대전화 옆면의 튀어나온 볼륨 버튼 옆에 있는 평평한 버튼입니다.\n\n전원 버튼을 누르면 화면이 꺼집니다."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"더 많은 옵션을 확인하려면 휴대전화를 잠금 해제하세요."</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"더 많은 옵션을 확인하려면 태블릿을 잠금 해제하세요."</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"더 많은 옵션을 확인하려면 기기를 잠금 해제하세요."</string>
diff --git a/packages/SystemUI/res-product/values-ky/strings.xml b/packages/SystemUI/res-product/values-ky/strings.xml
index 7c5472941a03..491de92fdea5 100644
--- a/packages/SystemUI/res-product/values-ky/strings.xml
+++ b/packages/SystemUI/res-product/values-ky/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык нерселер өчүрүлөт."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин планшетиңизди бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин телефонуңузду бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Манжа изинин сенсору кубат баскычында жайгашкан. Бул планшеттин четиндеги үндү катуулатуу/акырындатуу баскычынын жанындагы жалпак баскыч.\n\nКубат баскычы басылса, экран өчөт."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Манжа изинин сенсору кубат баскычында жайгашкан. Ал түзмөктүн четиндеги үндү катуулатуу/акырындатуу баскычынын жанындагы жалпак баскыч.\n\nКубат баскычы басылса, экран өчөт."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Манжа изинин сенсору кубат баскычында жайгашкан. Ал телефондун четиндеги үндү катуулатуу/акырындатуу баскычынын жанындагы жалпак баскыч.\n\nКубат баскычы басылса, экран өчөт."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Дагы башка параметрлерди көрүү үчүн телефонуңуздун кулпусун ачыңыз"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Дагы башка параметрлерди көрүү үчүн планшетиңиздин кулпусун ачыңыз"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Дагы башка параметрлерди көрүү үчүн түзмөгүңүздүн кулпусун ачыңыз"</string>
diff --git a/packages/SystemUI/res-product/values-lo/strings.xml b/packages/SystemUI/res-product/values-lo/strings.xml
index b6479d689f7d..e0c1bc0e246d 100644
--- a/packages/SystemUI/res-product/values-lo/strings.xml
+++ b/packages/SystemUI/res-product/values-lo/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບຜິດ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອແລ້ວ. ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຈະຖືກລຶບອອກ, ເຊິ່ງຈະລຶບຂໍ້ມູນໂປຣໄຟລ໌ທັງໝົດອອກນຳ."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກແຕ້ມຜິດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ທ່ານຈະຖືກຖາມໃຫ້ປົດລັອກແທັບເລັດຂອງທ່ານດ້ວຍການເຂົ້າສູ່ລະບົບໂດຍໃຊ້ອີເມວຂອງທ່ານ.\n\n ກະລຸນາລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER_2">%3$d</xliff:g> ວິນາທີ."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກແຕ້ມຜິດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ທ່ານຈະຖືກຖາມໃຫ້ປົດໂທລະສັບຂອງທ່ານດ້ວຍການເຂົ້າສູ່ລະບົບໂດຍໃຊ້ບັນຊີອີເມວ.\n\n ກະລຸນາລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER_2">%3$d</xliff:g> ວິນາທີ."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ເຊັນເຊີລາຍນິ້ວມືແມ່ນຢູ່ປຸ່ມເປີດປິດ. ມັນເປັນປຸ່ມຮາບພຽງທີ່ຢູ່ຖັດຈາກປຸ່ມລະດັບສຽງທີ່ຍົກຂຶ້ນມາຢູ່ຂອບຂອງແທັບເລັດ.\n\nການກົດປຸ່ມເປີດປິດຈະປິດໜ້າຈໍ."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ເຊັນເຊີລາຍນິ້ວມືແມ່ນຢູ່ປຸ່ມເປີດປິດ. ມັນເປັນປຸ່ມຮາບພຽງທີ່ຢູ່ຖັດຈາກປຸ່ມລະດັບສຽງທີ່ຍົກຂຶ້ນມາຢູ່ຂອບຂອງອຸປະກອນ.\n\nການກົດປຸ່ມເປີດປິດຈະປິດໜ້າຈໍ."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ເຊັນເຊີລາຍນິ້ວມືແມ່ນຢູ່ປຸ່ມເປີດປິດ. ມັນເປັນປຸ່ມຮາບພຽງທີ່ຢູ່ຖັດຈາກປຸ່ມລະດັບສຽງທີ່ຍົກຂຶ້ນມາຢູ່ຂອບຂອງໂທລະສັບ.\n\nການກົດປຸ່ມເປີດປິດຈະປິດໜ້າຈໍ."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ປົດລັອກໂທລະສັບຂອງທ່ານເພື່ອໃຊ້ຕົວເລືອກເພີ່ມເຕີມ"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ປົດລັອກແທັບເລັດຂອງທ່ານເພື່ອໃຊ້ຕົວເລືອກເພີ່ມເຕີມ"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ປົດລັອກອຸປະກອນຂອງທ່ານເພື່ອໃຊ້ຕົວເລືອກເພີ່ມເຕີມ"</string>
diff --git a/packages/SystemUI/res-product/values-lt/strings.xml b/packages/SystemUI/res-product/values-lt/strings.xml
index 560e36e72c15..99fdd65344a2 100644
--- a/packages/SystemUI/res-product/values-lt/strings.xml
+++ b/packages/SystemUI/res-product/values-lt/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Darbo profilis bus pašalintas ir visi profilio duomenys bus ištrinti."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai nupiešėte atrakinimo piešinį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. būsite paprašyti atrakinti planšetinį kompiuterį naudodami el. pašto paskyrą.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai nupiešėte atrakinimo piešinį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. būsite paprašyti atrakinti telefoną naudodami el. pašto paskyrą.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Piršto atspaudo jutiklis yra ant maitinimo mygtuko. Tai yra plokščias mygtukas šalia iškilusio garsumo mygtuko ant planšetinio kompiuterio krašto.\n\nPaspaudus maitinimo mygtuką išjungiamas ekranas."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Piršto atspaudo jutiklis yra ant maitinimo mygtuko. Tai yra plokščias mygtukas šalia iškilusio garsumo mygtuko ant įrenginio krašto.\n\nPaspaudus maitinimo mygtuką išjungiamas ekranas."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Piršto atspaudo jutiklis yra ant maitinimo mygtuko. Tai yra plokščias mygtukas šalia iškilusio garsumo mygtuko ant telefono krašto.\n\nPaspaudus maitinimo mygtuką išjungiamas ekranas."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Atrakinkite telefoną, kad galėtumėte naudoti daugiau parinkčių"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Atrakinkite planšetinį kompiuterį, kad galėtumėte naudoti daugiau parinkčių"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Atrakinkite įrenginį, kad galėtumėte naudoti daugiau parinkčių"</string>
diff --git a/packages/SystemUI/res-product/values-lv/strings.xml b/packages/SystemUI/res-product/values-lv/strings.xml
index 3c64f62e0614..7159562efb9b 100644
--- a/packages/SystemUI/res-product/values-lv/strings.xml
+++ b/packages/SystemUI/res-product/values-lv/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Darba profils tiks noņemts, kā arī visi profila dati tiks dzēsti."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nepareizi norādījāt atbloķēšanas kombināciju. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> neveiksmīga(-iem) mēģinājuma(-iem) planšetdators būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundes(-ēm)."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nepareizi norādījāt atbloķēšanas kombināciju. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) tālrunis būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundes(-ēm)."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Pirksta nospieduma sensors atrodas uz barošanas pogas. Barošanas poga ir plakanā poga, kas atrodas blakus augstākai skaļuma pogai planšetdatora sānos.\n\nNospiežot barošanas pogu, tiek izslēgts ekrāns."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Pirksta nospieduma sensors atrodas uz barošanas pogas. Barošanas poga ir plakanā poga, kas atrodas blakus augstākai skaļuma pogai ierīces sānos.\n\nNospiežot barošanas pogu, tiek izslēgts ekrāns."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Pirksta nospieduma sensors atrodas uz barošanas pogas. Barošanas poga ir plakanā poga, kas atrodas blakus augstākai skaļuma pogai tālruņa sānos.\n\nNospiežot barošanas pogu, tiek izslēgts ekrāns."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Atbloķējiet tālruni, lai skatītu citas opcijas."</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Atbloķējiet planšetdatoru, lai skatītu citas opcijas."</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Atbloķējiet ierīci, lai skatītu citas opcijas."</string>
diff --git a/packages/SystemUI/res-product/values-mk/strings.xml b/packages/SystemUI/res-product/values-mk/strings.xml
index d5895bfcae3a..c8358ff68ed1 100644
--- a/packages/SystemUI/res-product/values-mk/strings.xml
+++ b/packages/SystemUI/res-product/values-mk/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Погрешно се обидовте да го отклучите телефонот <xliff:g id="NUMBER">%d</xliff:g> пати. Работниот профил ќе се отстрани, со што ќе се избришат сите податоци на профилот."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Погрешно ја употребивте вашата шема на отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, ќе побараме да го отклучите таблетот со сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Погрешно ја употребивте вашата шема на отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, ќе побараме да го отклучите телефонот со сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сензорот за отпечатоци се наоѓа на копчето за вклучување. Тоа е рамното копче веднаш до подигнатото копче за јачина на звук на работ на таблетот.\n\nАко го притиснете копчето за вклучување, ќе се исклучи екранот."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сензорот за отпечатоци се наоѓа на копчето за вклучување. Тоа е рамното копче веднаш до подигнатото копче за јачина на звук на работ на уредот.\n\nАко го притиснете копчето за вклучување, ќе се исклучи екранот."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сензорот за отпечатоци се наоѓа на копчето за вклучување. Тоа е рамното копче веднаш до подигнатото копче за јачина на звук на работ на телефонот.\n\nАко го притиснете копчето за вклучување, ќе се исклучи екранот."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Отклучето го вашиот телефон за повеќе опции"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Отклучето го вашиот таблет за повеќе опции"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Отклучето го вашиот уред за повеќе опции"</string>
diff --git a/packages/SystemUI/res-product/values-ml/strings.xml b/packages/SystemUI/res-product/values-ml/strings.xml
index 59f3eb59271e..aa98f291abba 100644
--- a/packages/SystemUI/res-product/values-ml/strings.xml
+++ b/packages/SystemUI/res-product/values-ml/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ഫോൺ അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. ഔദ്യോഗിക പ്രൊഫൈൽ നീക്കം ചെയ്യപ്പെടുകയും, അതുവഴി എല്ലാ പ്രൊഫൈൽ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ അൺലോക്ക് പാറ്റേൺ വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, ഒരു ഇമെയിൽ അക്കൗണ്ടുപയോഗിച്ച് ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കന്റ് കഴിഞ്ഞ് വീണ്ടും ശ്രമിക്കുക."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ അൺലോക്ക് പാറ്റേൺ വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, ഒരു ഇമെയിൽ അക്കൗണ്ടുപയോഗിച്ച് ഫോൺ അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കന്റ് കഴിഞ്ഞ് വീണ്ടും ശ്രമിക്കുക."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"പവർ ബട്ടണിലാണ് ഫിംഗർപ്രിന്റ് സെൻസർ ഉള്ളത്. ടാബ്‌ലെറ്റിന്റെ അരികിൽ ഉയർന്ന് നിൽക്കുന്ന ശബ്ദ ബട്ടണിന്റെ അടുത്തുള്ള പരന്ന ബട്ടൺ ആണ് ഇത്.\n\nപവർ ബട്ടൺ അമർത്തുമ്പോൾ സ്ക്രീൻ ഓഫാകും."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"പവർ ബട്ടണിലാണ് ഫിംഗർപ്രിന്റ് സെൻസർ ഉള്ളത്. ഉപകരണത്തിന്റെ അരികിൽ ഉയർന്ന് നിൽക്കുന്ന ശബ്ദ ബട്ടണിന്റെ അടുത്തുള്ള പരന്ന ബട്ടൺ ആണ് ഇത്.\n\nപവർ ബട്ടൺ അമർത്തുമ്പോൾ സ്ക്രീൻ ഓഫാകും."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"പവർ ബട്ടണിലാണ് ഫിംഗർപ്രിന്റ് സെൻസർ ഉള്ളത്. ഫോണിന്റെ അരികിൽ ഉയർന്ന് നിൽക്കുന്ന ശബ്ദ ബട്ടണിന്റെ അടുത്തുള്ള പരന്ന ബട്ടൺ ആണ് ഇത്.\n\nപവർ ബട്ടൺ അമർത്തുമ്പോൾ സ്ക്രീൻ ഓഫാകും."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് നിങ്ങളുടെ ഫോൺ അൺലോക്ക് ചെയ്യുക"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് നിങ്ങളുടെ ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യുക"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് നിങ്ങളുടെ ഉപകരണം അൺലോക്ക് ചെയ്യുക"</string>
diff --git a/packages/SystemUI/res-product/values-mn/strings.xml b/packages/SystemUI/res-product/values-mn/strings.xml
index 41eb52d1c1d7..57333488698a 100644
--- a/packages/SystemUI/res-product/values-mn/strings.xml
+++ b/packages/SystemUI/res-product/values-mn/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийсэн байна. Ажлын профайлыг устгах бөгөөд ингэснээр профайлын бүх өгөгдлийг устгах болно."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Та тайлах хээгээ <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурсан байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу зурсны дараа та имэйл бүртгэл ашиглан таблетынхаа түгжээг тайлах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Та тайлах хээгээ <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурсан байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу зурсны дараа та имэйл бүртгэл ашиглан утасныхаа түгжээг тайлах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Хурууны хээ мэдрэгч асаах/унтраах товчин дээр байдаг. Энэ нь таблетын ирмэг дээрх дууны түвшний товгор товчлуурын хажууд байх хавтгай товчлуур юм.\n\nАсаах/унтраах товчийг дарснаар дэлгэц унтарна."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Хурууны хээ мэдрэгч асаах/унтраах товчин дээр байдаг. Энэ нь төхөөрөмжийн ирмэг дээрх дууны түвшний товгор товчлуурын хажууд байх хавтгай товчлуур юм.\n\nАсаах/унтраах товчийг дарснаар дэлгэц унтарна."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Хурууны хээ мэдрэгч асаах/унтраах товчин дээр байдаг. Энэ нь утасны ирмэг дээрх дууны түвшний товгор товчлуурын хажууд байх хавтгай товчлуур юм.\n\nАсаах/унтраах товчийг дарснаар дэлгэц унтарна."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Бусад сонголтыг харахын тулд утасныхаа түгжээг тайлна уу"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Бусад сонголтыг харахын тулд таблетынхаа түгжээг тайлна уу"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Бусад сонголтыг харахын тулд төхөөрөмжийнхөө түгжээг тайлна уу"</string>
diff --git a/packages/SystemUI/res-product/values-mr/strings.xml b/packages/SystemUI/res-product/values-mr/strings.xml
index ec277ccd9b9e..9626426b41ca 100644
--- a/packages/SystemUI/res-product/values-mr/strings.xml
+++ b/packages/SystemUI/res-product/values-mr/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. कार्य प्रोफाइल काढली जाईल, त्यामुळे सर्व प्रोफाइल डेटा हटवला जाईल."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा टॅबलेट अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा फोन अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"फिंगरप्रिंट सेन्सर हे पॉवर बटणावर आहे. हे टॅबलेटच्या कडेला वरती आलेल्या व्हॉल्यूम बटणाच्या बाजूला असलेले सपाट बटण आहे.\n\nपॉवर बटण प्रेस केल्याने स्क्रीन बंद होते."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"फिंगरप्रिंट सेन्सर हे पॉवर बटणावर आहे. हे डिव्हाइसच्या कडेला वरती आलेल्या व्हॉल्यूम बटणाच्या बाजूला असलेले सपाट बटण आहे.\n\nपॉवर बटण प्रेस केल्याने स्क्रीन बंद होते."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"फिंगरप्रिंट सेन्सर हे पॉवर बटणावर आहे. हे फोनच्या कडेला वरती आलेल्या व्हॉल्यूम बटणाच्या बाजूला असलेले सपाट बटण आहे.\n\nपॉवर बटण प्रेस केल्याने स्क्रीन बंद होते."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"आणखी पर्यायांसाठी तुमचा फोन अनलॉक करा"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"आणखी पर्यायांसाठी तुमचा टॅबलेट अनलॉक करा"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"आणखी पर्यायांसाठी तुमचे डिव्हाइस अनलॉक करा"</string>
diff --git a/packages/SystemUI/res-product/values-ms/strings.xml b/packages/SystemUI/res-product/values-ms/strings.xml
index 7b247a0fdb94..09936468eb83 100644
--- a/packages/SystemUI/res-product/values-ms/strings.xml
+++ b/packages/SystemUI/res-product/values-ms/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Profil kerja ini akan dialih keluar sekali gus memadamkan semua data profil."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, anda akan diminta membuka kunci tablet anda menggunakan akaun e-mel.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> saat."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, anda akan diminta membuka kunci telefon anda menggunakan akaun e-mel.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> saat."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Penderia cap jari berada pada butang kuasa. Penderia cap jari ialah butang rata yang terletak bersebelahan butang kelantangan yang timbul pada bahagian tepi tablet.\n\nPenekanan butang kuasa akan mematikan skrin."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Penderia cap jari berada pada butang kuasa. Penderia cap jari ialah butang rata yang terletak bersebelahan butang kelantangan yang timbul pada bahagian tepi peranti.\n\nPenekanan butang kuasa akan mematikan skrin."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Penderia cap jari berada pada butang kuasa. Penderia cap jari ialah butang rata yang terletak bersebelahan butang kelantangan yang timbul pada bahagian tepi telefon.\n\nPenekanan butang kuasa akan mematikan skrin."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Buka kunci telefon anda untuk mendapatkan lagi pilihan"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Buka kunci tablet anda untuk mendapatkan lagi pilihan"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Buka kunci peranti anda untuk mendapatkan lagi pilihan"</string>
diff --git a/packages/SystemUI/res-product/values-my/strings.xml b/packages/SystemUI/res-product/values-my/strings.xml
index d15df82aa6d6..cd35ebf5d7ec 100644
--- a/packages/SystemUI/res-product/values-my/strings.xml
+++ b/packages/SystemUI/res-product/values-my/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ဖုန်းကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ အလုပ်ပရိုဖိုင်ကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး ပရိုဖိုင်ဒေတာ အားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"သင်သည် သင်၏ လော့ခ်ဖွင့်ခြင်းပုံစံကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ ဆွဲခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းပြီးသည့်နောက်တွင် သင့်အီးမေးလ်အကောင့်အား အသုံးပြု၍ တက်ဘလက်ကို လော့ခ်ဖွင့်ရန် တောင်းဆိုသွားပါမည်။\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"သင်သည် သင်၏ လော့ခ်ဖွင့်ခြင်းပုံစံကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ ဆွဲခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းပြီးသည့်နောက်တွင် သင့်အီးမေးလ်အကောင့်အား အသုံးပြု၍ ဖုန်းကို လော့ခ်ဖွင့်ရန် တောင်းဆိုသွားပါမည်။\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"လက်ဗွေ အာရုံခံကိရိယာသည် ဖွင့်ပိတ်ခလုတ်ပေါ်တွင် ရှိသည်။ တက်ဘလက်ဘေးဘက်ရှိ မြင့်တက်နေသည့်အသံထိန်း ခလုတ်၏ ကပ်လျက်ရှိ ခလုတ်ပြားဖြစ်သည်။\n\nဖွင့်ပိတ်ခလုတ်ကိုနှိပ်ပါက ဖန်သားပြင်ပိတ်သွားမည်။"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"လက်ဗွေ အာရုံခံကိရိယာသည် ဖွင့်ပိတ်ခလုတ်ပေါ်တွင် ရှိသည်။ စက်ဘေးဘက်ရှိ မြင့်တက်နေသည့်အသံထိန်း ခလုတ်၏ ကပ်လျက်ရှိ ခလုတ်ပြားဖြစ်သည်။\n\nဖွင့်ပိတ်ခလုတ်ကိုနှိပ်ပါက ဖန်သားပြင်ပိတ်သွားမည်။"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"လက်ဗွေ အာရုံခံကိရိယာသည် ဖွင့်ပိတ်ခလုတ်ပေါ်တွင် ရှိသည်။ ဖုန်းဘေးဘက်ရှိ မြင့်တက်နေသည့်အသံထိန်း ခလုတ်၏ ကပ်လျက်ရှိ ခလုတ်ပြားဖြစ်သည်။\n\nဖွင့်ပိတ်ခလုတ်ကိုနှိပ်ပါက ဖန်သားပြင်ပိတ်သွားမည်။"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"နောက်ထပ် ထိန်းချုပ်မှုများအတွက် သင့်ဖုန်းကို လော့ခ်ဖွင့်ပါ"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"နောက်ထပ် ထိန်းချုပ်မှုများအတွက် သင့်တက်ဘလက်ကို လော့ခ်ဖွင့်ပါ"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"နောက်ထပ် ထိန်းချုပ်မှုများအတွက် သင့်စက်ကို လော့ခ်ဖွင့်ပါ"</string>
diff --git a/packages/SystemUI/res-product/values-nb/strings.xml b/packages/SystemUI/res-product/values-nb/strings.xml
index 816e9c182d9d..8af822a01ebb 100644
--- a/packages/SystemUI/res-product/values-nb/strings.xml
+++ b/packages/SystemUI/res-product/values-nb/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER">%d</xliff:g> ganger. Jobbprofilen blir fjernet, og alle profildataene blir slettet."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du har tegnet opplåsingsmønsteret feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk blir du bedt om å låse opp nettbrettet via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du har tegnet opplåsingsmønsteret feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk blir du bedt om å låse opp telefonen via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Fingeravtrykkssensoren er på av/på-knappen. Det er den flate knappen ved siden av den opphøyde volumknappen på kanten av nettbrettet.\n\nHvis du trykker på av/på-knappen, slås skjermen av."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Fingeravtrykkssensoren er på av/på-knappen. Det er den flate knappen ved siden av den opphøyde volumknappen på kanten av enheten.\n\nHvis du trykker på av/på-knappen, slås skjermen av."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Fingeravtrykkssensoren er på av/på-knappen. Det er den flate knappen ved siden av den opphøyde volumknappen på kanten av telefonen.\n\nHvis du trykker på av/på-knappen, slås skjermen av."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Lås opp telefonen din for å få flere alternativer"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Lås opp nettbrettet ditt for å få flere alternativer"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lås opp enheten din for å få flere alternativer"</string>
diff --git a/packages/SystemUI/res-product/values-ne/strings.xml b/packages/SystemUI/res-product/values-ne/strings.xml
index eef80b27b212..fe40e6928f73 100644
--- a/packages/SystemUI/res-product/values-ne/strings.xml
+++ b/packages/SystemUI/res-product/values-ne/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"तपाईंले <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। कार्य प्रोफाइललाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक आफ्नो अनलक गर्ने ढाँचा गलत रूपमा कोर्नुभयो। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, तपाईंलाई एउटा इमेल खाता प्रयोग गरेर आफ्नो ट्याब्लेट अनलक गर्न आग्रह गरिने छ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक आफ्नो अनलक गर्ने ढाँचा गलत रूपमा कोर्नुभयो। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, तपाईंलाई एउटा इमेल खाता प्रयोग गरेर आफ्नो फोन अनलक गर्न आग्रह गरिने छ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"फिंगरप्रिन्ट सेन्सर पावर बटनमा छ। यो बटन ट्याब्लेटको किनारामा रहेको थोरै उचालिएको भोल्युम बटनको छेउमा रहेको समतल बटन हो।\n\nतपाईंले पावर बटन थिच्नुभयो भने स्क्रिन अफ हुन्छ।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"फिंगरप्रिन्ट सेन्सर पावर बटनमा छ। यो बटन डिभाइसको किनारामा रहेको थोरै उचालिएको भोल्युम बटनको छेउमा रहेको समतल बटन हो।\n\nतपाईंले पावर बटन थिच्नुभयो भने स्क्रिन अफ हुन्छ।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"फिंगरप्रिन्ट सेन्सर पावर बटनमा छ। यो बटन फोनको किनारामा रहेको थोरै उचालिएको भोल्युम बटनको छेउमा रहेको समतल बटन हो।\n\nतपाईंले पावर बटन थिच्नुभयो भने स्क्रिन अफ हुन्छ।"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"थप विकल्पहरू हेर्न आफ्नो फोन अनलक गर्नुहोस्"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"थप विकल्पहरू हेर्न आफ्नो ट्याब्लेट अनलक गर्नुहोस्"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"थप विकल्पहरू हेर्न आफ्नो डिभाइस अनलक गर्नुहोस्"</string>
diff --git a/packages/SystemUI/res-product/values-nl/strings.xml b/packages/SystemUI/res-product/values-nl/strings.xml
index 95e32efb7f87..7db0d31a3b52 100644
--- a/packages/SystemUI/res-product/values-nl/strings.xml
+++ b/packages/SystemUI/res-product/values-nl/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Het werkprofiel wordt verwijderd, waardoor alle profielgegevens worden verwijderd."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt je gevraagd je tablet te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%3$d</xliff:g> seconden opnieuw."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt je gevraagd je telefoon te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%3$d</xliff:g> seconden opnieuw."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Je vindt de vingerafdruksensor onder de aan/uit-knop. Het is de platte knop naast de verhoogde volumeknop aan de zijkant van de tablet.\n\nAls je op de aan/uit-knop drukt, gaat het scherm uit."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Je vindt de vingerafdruksensor onder de aan/uit-knop. Het is de platte knop naast de verhoogde volumeknop aan de zijkant van het apparaat.\n\nAls je op de aan/uit-knop drukt, gaat het scherm uit."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Je vindt de vingerafdruksensor onder de aan/uit-knop. Het is de platte knop naast de verhoogde volumeknop aan de zijkant van de telefoon.\n\nAls je op de aan/uit-knop drukt, gaat het scherm uit."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Ontgrendel je telefoon voor meer opties"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Ontgrendel je tablet voor meer opties"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ontgrendel je apparaat voor meer opties"</string>
diff --git a/packages/SystemUI/res-product/values-or/strings.xml b/packages/SystemUI/res-product/values-or/strings.xml
index e0d9366de750..2da509ef5696 100644
--- a/packages/SystemUI/res-product/values-or/strings.xml
+++ b/packages/SystemUI/res-product/values-or/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ<xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। କାର୍ଯ୍ୟ ପ୍ରୋଫାଇଲ୍ ବାହାର କରିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ପ୍ରୋଫାଇଲ୍ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ଆପଣ ଆପଣଙ୍କ ଅନ୍‌ଲକ୍ ପାଟର୍ନକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଡ୍ର କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଆପଣଙ୍କୁ ଏକ ଇମେଲ୍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ଆପଣଙ୍କ ଟାବ୍‌ଲୋଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବା ପାଇଁ କୁହାଯିବ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ଆପଣ ଆପଣଙ୍କ ଅନ୍‌ଲକ୍ ପାଟର୍ନକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଡ୍ର କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଆପଣଙ୍କୁ ଏକ ଇମେଲ୍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ଆପଣଙ୍କ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍‌ କରିବା ପାଇଁ କୁହାଯିବ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ଟିପଚିହ୍ନ ସେନ୍ସର ପାୱାର ବଟନରେ ଅଛି। ଟାବଲେଟର ଧାରରେ ଥିବା ବଢ଼ାଯାଇଥିବା ଭଲ୍ୟୁମ ବଟନ ପାଖରେ ଏହା ଫ୍ଲାଟ ବଟନ ଅଟେ।\n\nପାୱାର ବଟନକୁ ଦବାଇବା ଦ୍ୱାରା ସ୍କ୍ରିନ ବନ୍ଦ ହୋଇଥାଏ।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ଟିପଚିହ୍ନ ସେନ୍ସର ପାୱାର ବଟନରେ ଅଛି। ଡିଭାଇସର ଧାରରେ ଥିବା ବଢ଼ାଯାଇଥିବା ଭଲ୍ୟୁମ ବଟନ ପାଖରେ ଏହା ଫ୍ଲାଟ ବଟନ ଅଟେ।\n\nପାୱାର ବଟନକୁ ଦବାଇବା ଦ୍ୱାରା ସ୍କ୍ରିନ ବନ୍ଦ ହୋଇଥାଏ।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ଟିପଚିହ୍ନ ସେନ୍ସର ପାୱାର ବଟନରେ ଅଛି। ଫୋନର ଧାରରେ ଥିବା ବଢ଼ାଯାଇଥିବା ଭଲ୍ୟୁମ ବଟନ ପାଖରେ ଏହା ଫ୍ଲାଟ ବଟନ ଅଟେ।\n\nପାୱାର ବଟନକୁ ଦବାଇବା ଦ୍ୱାରା ସ୍କ୍ରିନ ବନ୍ଦ ହୋଇଥାଏ।"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ଅଧିକ ବିକଳ୍ପ ପାଇଁ ଆପଣଙ୍କ ଫୋନ୍ ଅନଲକ୍ କରନ୍ତୁ"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ଅଧିକ ବିକଳ୍ପ ପାଇଁ ଆପଣଙ୍କ ଟାବଲେଟ୍ ଅନଲକ୍ କରନ୍ତୁ"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ଅଧିକ ବିକଳ୍ପ ପାଇଁ ଆପଣଙ୍କ ଡିଭାଇସ୍ ଅନଲକ୍ କରନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res-product/values-pa/strings.xml b/packages/SystemUI/res-product/values-pa/strings.xml
index d65998b3075c..ec7eca1d6d48 100644
--- a/packages/SystemUI/res-product/values-pa/strings.xml
+++ b/packages/SystemUI/res-product/values-pa/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣੇ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਪਾਵਰ ਬਟਨ \'ਤੇ ਹੈ। ਇਹ ਟੈਬਲੈੱਟ ਦੇ ਕਿਨਾਰੇ \'ਤੇ ਅਜਿਹਾ ਸਮਤਲ ਬਟਨ ਹੁੰਦਾ ਹੈ ਜੋ ਉੱਭਰੇ ਹੋਏ ਅਵਾਜ਼ ਬਟਨ ਦੇ ਅੱਗੇ ਹੁੰਦਾ ਹੈ।\n\nਪਾਵਰ ਬਟਨ ਦਬਾਉਣ ਨਾਲ ਸਕ੍ਰੀਨ ਬੰਦ ਹੋ ਜਾਂਦੀ ਹੈ।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਪਾਵਰ ਬਟਨ \'ਤੇ ਹੈ। ਇਹ ਡੀਵਾਈਸ ਦੇ ਕਿਨਾਰੇ \'ਤੇ ਅਜਿਹਾ ਸਮਤਲ ਬਟਨ ਹੁੰਦਾ ਹੈ ਜੋ ਉੱਭਰੇ ਹੋਏ ਅਵਾਜ਼ ਬਟਨ ਦੇ ਅੱਗੇ ਹੁੰਦਾ ਹੈ।\n\nਪਾਵਰ ਬਟਨ ਦਬਾਉਣ ਨਾਲ ਸਕ੍ਰੀਨ ਬੰਦ ਹੋ ਜਾਂਦੀ ਹੈ।"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਪਾਵਰ ਬਟਨ \'ਤੇ ਹੈ। ਇਹ ਫ਼ੋਨ ਦੇ ਕਿਨਾਰੇ \'ਤੇ ਅਜਿਹਾ ਸਮਤਲ ਬਟਨ ਹੁੰਦਾ ਹੈ ਜੋ ਉੱਭਰੇ ਹੋਏ ਅਵਾਜ਼ ਬਟਨ ਦੇ ਅੱਗੇ ਹੁੰਦਾ ਹੈ।\n\nਪਾਵਰ ਬਟਨ ਦਬਾਉਣ ਨਾਲ ਸਕ੍ਰੀਨ ਬੰਦ ਹੋ ਜਾਂਦੀ ਹੈ।"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰੋ"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਆਪਣਾ ਟੈਬਲੈੱਟ ਅਣਲਾਕ ਕਰੋ"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਆਪਣਾ ਡੀਵਾਈਸ ਅਣਲਾਕ ਕਰੋ"</string>
diff --git a/packages/SystemUI/res-product/values-pl/strings.xml b/packages/SystemUI/res-product/values-pl/strings.xml
index f6360ebb42a7..1b9d43b08549 100644
--- a/packages/SystemUI/res-product/values-pl/strings.xml
+++ b/packages/SystemUI/res-product/values-pl/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować telefon. Profil służbowy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowano wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie tabletu przy użyciu konta e-mail.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowano wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie telefonu przy użyciu konta e-mail.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Czytnik linii papilarnych znajduje się na przycisku zasilania. To płaski przycisk przy uniesionym przycisku głośności na krawędzi tabletu.\n\nNaciśnięcie przycisku zasilania wyłącza ekran."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Czytnik linii papilarnych znajduje się na przycisku zasilania. To płaski przycisk przy uniesionym przycisku głośności na krawędzi urządzenia.\n\nNaciśnięcie przycisku zasilania wyłącza ekran."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Czytnik linii papilarnych znajduje się na przycisku zasilania. To płaski przycisk przy uniesionym przycisku głośności na krawędzi telefonu.\n\nNaciśnięcie przycisku zasilania wyłącza ekran."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Odblokuj telefon, by wyświetlić więcej opcji"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Odblokuj tablet, by wyświetlić więcej opcji"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Odblokuj urządzenie, by wyświetlić więcej opcji"</string>
diff --git a/packages/SystemUI/res-product/values-pt-rBR/strings.xml b/packages/SystemUI/res-product/values-pt-rBR/strings.xml
index fff7606d4732..3130966cb550 100644
--- a/packages/SystemUI/res-product/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-product/values-pt-rBR/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o smartphone.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do tablet.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do dispositivo.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do smartphone.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloqueie seu smartphone para ver mais opções"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloqueie seu tablet para ver mais opções"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueie seu dispositivo para ver mais opções"</string>
diff --git a/packages/SystemUI/res-product/values-pt-rPT/strings.xml b/packages/SystemUI/res-product/values-pt-rPT/strings.xml
index 678bd266cd14..6ff8a1292809 100644
--- a/packages/SystemUI/res-product/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-product/values-pt-rPT/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que eliminará todos os dados do mesmo."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Desenhou o padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, ser-lhe-á pedido para desbloquear o tablet através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Desenhou o padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, ser-lhe-á pedido para desbloquear o telemóvel através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"O sensor de impressões digitais encontra-se no botão ligar/desligar. É o botão plano junto ao botão de volume com relevo na extremidade do tablet.\n\nPremir o botão ligar/desligar desativa o ecrã."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"O sensor de impressões digitais encontra-se no botão ligar/desligar. É o botão plano junto ao botão de volume com relevo na extremidade do dispositivo.\n\nPremir o botão ligar/desligar desativa o ecrã."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"O sensor de impressões digitais encontra-se no botão ligar/desligar. É o botão plano junto ao botão de volume com relevo na extremidade do telemóvel.\n\nPremir o botão ligar/desligar desativa o ecrã."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloqueie o telemóvel para obter mais opções."</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloqueie o tablet para obter mais opções."</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueie o dispositivo para obter mais opções."</string>
diff --git a/packages/SystemUI/res-product/values-pt/strings.xml b/packages/SystemUI/res-product/values-pt/strings.xml
index fff7606d4732..3130966cb550 100644
--- a/packages/SystemUI/res-product/values-pt/strings.xml
+++ b/packages/SystemUI/res-product/values-pt/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o smartphone.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do tablet.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do dispositivo.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do smartphone.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloqueie seu smartphone para ver mais opções"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloqueie seu tablet para ver mais opções"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueie seu dispositivo para ver mais opções"</string>
diff --git a/packages/SystemUI/res-product/values-ro/strings.xml b/packages/SystemUI/res-product/values-ro/strings.xml
index 471f01e678e1..572f8e642c0a 100644
--- a/packages/SystemUI/res-product/values-ro/strings.xml
+++ b/packages/SystemUI/res-product/values-ro/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Ai făcut <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Ai desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, ți se va solicita să deblochezi tableta cu ajutorul unui cont de e-mail.\n\n Încearcă din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> secunde."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ai desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, ți se va solicita să deblochezi telefonul cu ajutorul unui cont de e-mail.\n\n Încearcă din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> secunde."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Senzorul de amprentă se află pe butonul de pornire. Este butonul plat de lângă butonul de volum în relief de pe marginea tabletei.\n\nDacă apeși butonul de pornire, ecranul se va dezactiva."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Senzorul de amprentă se află pe butonul de pornire. Este butonul plat de lângă butonul de volum în relief de pe marginea dispozitivului.\n\nDacă apeși butonul de pornire, ecranul se va dezactiva."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Senzorul de amprentă se află pe butonul de pornire. Este butonul plat de lângă butonul de volum în relief de pe marginea telefonului.\n\nDacă apeși butonul de pornire, ecranul se va dezactiva."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Deblochează telefonul pentru mai multe opțiuni"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Deblochează tableta pentru mai multe opțiuni"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Deblochează dispozitivul pentru mai multe opțiuni"</string>
diff --git a/packages/SystemUI/res-product/values-ru/strings.xml b/packages/SystemUI/res-product/values-ru/strings.xml
index 0d0dd1ce1d68..af3fe75ee83c 100644
--- a/packages/SystemUI/res-product/values-ru/strings.xml
+++ b/packages/SystemUI/res-product/values-ru/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Вы несколько раз (<xliff:g id="NUMBER">%d</xliff:g>) не смогли разблокировать телефон. Рабочий профиль и все его данные будут удалены."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) ввели неверный графический ключ. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи вам будет предложено разблокировать планшет с помощью аккаунта электронной почты.\n\nПовторите попытку через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) ввели неверный графический ключ. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи вам будет предложено разблокировать телефон с помощью аккаунта электронной почты.\n\nПовторите попытку через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сканер отпечатков пальцев находится на кнопке питания. Это плоская кнопка рядом с приподнятой кнопкой регулировки громкости на боковой стороне устройства.\n\nНажав кнопку питания, вы выключите экран."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сканер отпечатков пальцев находится на кнопке питания. Это плоская кнопка рядом с приподнятой кнопкой регулировки громкости на боковой стороне устройства.\n\nНажав кнопку питания, вы выключите экран."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сканер отпечатков пальцев находится на кнопке питания. Это плоская кнопка рядом с приподнятой кнопкой регулировки громкости на боковой стороне устройства.\n\nНажав кнопку питания, вы выключите экран."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Чтобы посмотреть дополнительные параметры, разблокируйте телефон."</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Чтобы посмотреть дополнительные параметры, разблокируйте планшет."</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Чтобы посмотреть дополнительные параметры, разблокируйте устройство."</string>
diff --git a/packages/SystemUI/res-product/values-si/strings.xml b/packages/SystemUI/res-product/values-si/strings.xml
index 0d7b67dd6137..cdb29778364c 100644
--- a/packages/SystemUI/res-product/values-si/strings.xml
+++ b/packages/SystemUI/res-product/values-si/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. කාර්යාල පැතිකඩ ඉවත් කරනු ඇති අතර, එය සියලු පැතිකඩ දත්ත මකනු ඇත."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ඔබ අගුළු ඇරිමේ රටාව <xliff:g id="NUMBER_0">%1$d</xliff:g> වතාවක් වැරදියට ඇඳ ඇත. තවත් අසාර්ථක උත්සාහ <xliff:g id="NUMBER_1">%2$d</xliff:g> කින් පසුව, ඊ-තැපැල් ගිණුම භාවිතා කරමින් ඔබගේ ටැබ්ලටයේ අගුළු ඇරීමට ඔබට පවසනු ඇත.\n\n නැවත තත්පර <xliff:g id="NUMBER_2">%3$d</xliff:g> කින් උත්සාහ කරන්න."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ඔබ වැරදියට <xliff:g id="NUMBER_0">%1$d</xliff:g> වතාවක් ඔබගේ අගුළු හැරීමේ රටාව ඇඳ ඇත. අසාර්ථක උත්සහ කිරීම් <xliff:g id="NUMBER_1">%2$d</xliff:g> න් පසුව, ඔබගේ ඊ-තැපැල් ලිපිනය භාවිතයෙන් ඔබගේ දුරකථනය අගුළු හැරීමට ඔබගෙන් අසයි.\n\n තත්පර <xliff:g id="NUMBER_2">%3$d</xliff:g> න් පසුව නැවත උත්සහ කරන්න."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ඇඟිලි සලකුණු සංවේදකය බල බොත්තම මත ඇත. එය ටැබ්ලටයෙහි කෙළවරේ ඇති ඉහළ හඬ පරිමා බොත්තම අසල ඇති පැතලි බොත්තමයි.\n\nබල බොත්තම එබීම තිරය ක්‍රියා විරහිත කරයි."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ඇඟිලි සලකුණු සංවේදකය බල බොත්තම මත ඇත. එය උපාංගයෙහි කෙළවරේ ඇති ඉහළ හඬ පරිමා බොත්තම අසල ඇති පැතලි බොත්තමයි.\n\nබල බොත්තම එබීම තිරය ක්‍රියා විරහිත කරයි."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ඇඟිලි සලකුණු සංවේදකය බල බොත්තම මත ඇත. එය දුරකථනයෙහි කෙළවරේ ඇති ඉහළ හඬ පරිමා බොත්තම අසල ඇති පැතලි බොත්තමයි.\n\nබල බොත්තම එබීම තිරය ක්‍රියා විරහිත කරයි."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"තව විකල්ප සඳහා ඔබේ දුරකථනය අගුලු හරින්න"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"තව විකල්ප සඳහා ඔබේ ටැබ්ලට් පරිගණකය අගුලු හරින්න"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"තව විකල්ප සඳහා ඔබේ උපාංගය අගුලු හරින්න"</string>
diff --git a/packages/SystemUI/res-product/values-sk/strings.xml b/packages/SystemUI/res-product/values-sk/strings.xml
index 3caddbeba367..60d984a42730 100644
--- a/packages/SystemUI/res-product/values-sk/strings.xml
+++ b/packages/SystemUI/res-product/values-sk/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefón ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>‑krát nesprávne odomknúť. Pracovný profil bude odstránený spolu so všetkými údajmi."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie tabletu pomocou e‑mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Už ste <xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie telefónu pomocou e‑mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Senzor odtlačkov prstov je na vypínači. Ide o ploché tlačidlo vedľa vypuklého tlačidla hlasitosti na okraji tabletu.\n\nStlačením vypínača vypnete obrazovku."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Senzor odtlačkov prstov je na vypínači. Ide o ploché tlačidlo vedľa vypuklého tlačidla hlasitosti na okraji zariadenia.\n\nStlačením vypínača vypnete obrazovku."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Senzor odtlačkov prstov je na vypínači. Ide o ploché tlačidlo vedľa vypuklého tlačidla hlasitosti na okraji telefónu.\n\nStlačením vypínača vypnete obrazovku."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Ak chcete zobraziť ďalšie možnosti, odomknite telefón"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Ak chcete zobraziť ďalšie možnosti, odomknite tablet"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ak chcete zobraziť ďalšie možnosti, odomknite zariadenie"</string>
diff --git a/packages/SystemUI/res-product/values-sl/strings.xml b/packages/SystemUI/res-product/values-sl/strings.xml
index 96ac31bb3c0c..bfa77168daed 100644
--- a/packages/SystemUI/res-product/values-sl/strings.xml
+++ b/packages/SystemUI/res-product/values-sl/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat. Delovni profil bo odstranjen in vsi podatki profila bodo izbrisani."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat napačno vnesli. Če ga neuspešno poskusite vnesti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, boste pozvani, da tablični računalnik odklenete z e-poštnim računom.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat napačno vnesli. Če ga neuspešno poskusite vnesti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, boste pozvani, da telefon odklenete z e-poštnim računom.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Tipalo prstnih odtisov je na gumbu za vklop. To je ploski gumb ob izbočenem gumbu za glasnost na robu tabličnega računalnika.\n\nČe pritisnete gumb za vklop, se zaslon izklopi."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Tipalo prstnih odtisov je na gumbu za vklop. To je ploski gumb ob izbočenem gumbu za glasnost na robu naprave.\n\nČe pritisnete gumb za vklop, se zaslon izklopi."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Tipalo prstnih odtisov je na gumbu za vklop. To je ploski gumb ob izbočenem gumbu za glasnost na robu telefona.\n\nČe pritisnete gumb za vklop, se zaslon izklopi."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Za več možnosti odklenite telefon"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Za več možnosti odklenite tablični računalnik"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Za več možnosti odklenite napravo"</string>
diff --git a/packages/SystemUI/res-product/values-sq/strings.xml b/packages/SystemUI/res-product/values-sq/strings.xml
index f552b29cf43d..50e2fd72dd51 100644
--- a/packages/SystemUI/res-product/values-sq/strings.xml
+++ b/packages/SystemUI/res-product/values-sq/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur telefonin. Profili i punës do të hiqet, gjë që do të fshijë të gjitha të dhënat e profilit."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Ke vizatuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses motivin tënd të shkyçjes. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, do të të duhet ta shkyçësh tabletin duke përdorur një llogari email-i.\n\n Provo sërish për <xliff:g id="NUMBER_2">%3$d</xliff:g> sekonda."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ke vizatuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses motivin tënd. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, do të të duhet ta shkyçësh telefonin duke përdorur një llogari email-i.\n\n Provo sërish për <xliff:g id="NUMBER_2">%3$d</xliff:g> sekonda."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Sensori i gjurmës së gishtit është në butonin e energjisë. Ai është butoni i rrafshët pranë butonit të ngritur të volumit në anë të tabletit.\n\nShtypja e butonit të energjisë e fik ekranin."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Sensori i gjurmës së gishtit është në butonin e energjisë. Ai është butoni i rrafshët pranë butonit të ngritur të volumit në anë të pajisjes.\n\nShtypja e butonit të energjisë e fik ekranin."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Sensori i gjurmës së gishtit është në butonin e energjisë. Ai është butoni i rrafshët pranë butonit të ngritur të volumit në anë të telefonit.\n\nShtypja e butonit të energjisë e fik ekranin."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Shkyçe telefonin për më shumë opsione"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Shkyçe tabletin për më shumë opsione"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Shkyçe pajisjen për më shumë opsione"</string>
diff --git a/packages/SystemUI/res-product/values-sr/strings.xml b/packages/SystemUI/res-product/values-sr/strings.xml
index f1e6eec01004..6868a984ac4f 100644
--- a/packages/SystemUI/res-product/values-sr/strings.xml
+++ b/packages/SystemUI/res-product/values-sr/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER">%d</xliff:g> пута. Уклонићемо пословни профил, чиме се бришу сви подаци са профила."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Нетачно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, затражићемо да откључате таблет помоћу имејл налога.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Нетачно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, затражићемо да откључате телефон помоћу имејл налога.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сензор за отисак прста се налази на дугмету за укључивање. То је равно дугме поред издигнутог дугмета за јачину звука на ивици таблета.\n\nПритиском на дугме за укључивање искључује се екран."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сензор за отисак прста се налази на дугмету за укључивање. То је равно дугме поред издигнутог дугмета за јачину звука на ивици уређаја.\n\nПритиском на дугме за укључивање искључује се екран."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сензор за отисак прста се налази на дугмету за укључивање. То је равно дугме поред издигнутог дугмета за јачину звука на ивици телефона.\n\nПритиском на дугме за укључивање искључује се екран."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Откључајте телефон за још опција"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Откључајте таблет за још опција"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Откључајте уређај за још опција"</string>
diff --git a/packages/SystemUI/res-product/values-sv/strings.xml b/packages/SystemUI/res-product/values-sv/strings.xml
index 397580f659f0..23045d795472 100644
--- a/packages/SystemUI/res-product/values-sv/strings.xml
+++ b/packages/SystemUI/res-product/values-sv/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du har försökt låsa upp telefonen på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Jobbprofilen tas bort och all profildata raderas."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök måste du låsa upp surfplattan med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök måste du låsa upp telefonen med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Fingeravtryckssensorn sitter på av/på-knappen. Det är den platta knappen bredvid den upphöjda volymknappen på kanten av surfplattan.\n\nOm du trycker på av/på-knappen stängs skärmen av."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Fingeravtryckssensorn sitter på av/på-knappen. Det är den platta knappen bredvid den upphöjda volymknappen på kanten av enheten.\n\nOm du trycker på av/på-knappen stängs skärmen av."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Fingeravtryckssensorn sitter på av/på-knappen. Det är den platta knappen bredvid den upphöjda volymknappen på kanten av telefonen.\n\nOm du trycker på av/på-knappen stängs skärmen av."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Lås upp telefonen för fler alternativ"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Lås upp surfplattan för fler alternativ"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lås upp enheten för fler alternativ"</string>
diff --git a/packages/SystemUI/res-product/values-sw/strings.xml b/packages/SystemUI/res-product/values-sw/strings.xml
index 863838fa2ce9..cc75af8755b4 100644
--- a/packages/SystemUI/res-product/values-sw/strings.xml
+++ b/packages/SystemUI/res-product/values-sw/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Umejaribu kufungua simu mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Wasifu wa kazini utaondolewa, hatua itakayofuta data yote ya wasifu."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Umeweka mchoro usio sahihi wa kufungua skrini mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> zaidi bila mafanikio, utaombwa ufungue kompyuta yako kibao kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Umeweka mchoro usio sahihi wa kufungua skrini mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, utaombwa ufungue simu yako kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Kitambuzi cha alama ya kidole kinapatikana kwenye kitufe cha kuwasha/kuzima. Ni kitufe bapa pembeni pa kitufe cha sauti kilichoinuka kwenye ukingo wa kompyuta kibao.\n\nUkibonyeza kitufe cha kuwasha/kuzima skrini itazima."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Kitambuzi cha alama ya kidole kinapatikana kwenye kitufe cha kuwasha/kuzima. Ni kitufe bapa pembeni pa kitufe cha sauti kilichoinuka kwenye ukingo wa kifaa.\n\nUkibonyeza kitufe cha kuwasha/kuzima skrini itazima."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Kitambuzi cha alama ya kidole kinapatikana kwenye kitufe cha kuwasha/kuzima. Ni kitufe bapa pembeni pa kitufe cha sauti kilichoinuka kwenye ukingo wa simu.\n\nUkibonyeza kitufe cha kuwasha/kuzima skrini itazima."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Fungua simu yako ili upate chaguo zaidi"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Fungua kompyuta yako kibao ili upate chaguo zaidi"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Fungua kifaa chako ili upate chaguo zaidi"</string>
diff --git a/packages/SystemUI/res-product/values-ta/strings.xml b/packages/SystemUI/res-product/values-ta/strings.xml
index 0582460eba83..1acbb728583a 100644
--- a/packages/SystemUI/res-product/values-ta/strings.xml
+++ b/packages/SystemUI/res-product/values-ta/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"மொபைலை அன்லாக் செய்ய, <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டதனால் பணிக் கணக்கு அகற்றப்படும். இதனால் அதிலுள்ள அனைத்துச் சுயவிவரத் தரவும் நீக்கப்படும்."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"அன்லாக் பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக வரைந்தால், மின்னஞ்சல் கணக்கைப் பயன்படுத்தி டேப்லெட்டை அன்லாக் செய்யும்படி கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"அன்லாக் பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக வரைந்தால், மின்னஞ்சல் கணக்கைப் பயன்படுத்தி மொபைலை அன்லாக் செய்யும்படி கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"\'கைரேகை சென்சார்\' பவர் பட்டனில் உள்ளது. இது டேப்லெட்டின் விளிம்பில் சற்று மேலெழும்பிய ஒலியளவு பட்டனுக்கு அருகில் இருக்கும் தட்டையான பட்டனாகும்.\n\nபவர் பட்டனை அழுத்தினால் திரை ஆஃப் ஆகும்."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"\'கைரேகை சென்சார்\' பவர் பட்டனில் உள்ளது. இது சாதனத்தின் விளிம்பில் சற்று மேலெழும்பிய ஒலியளவு பட்டனுக்கு அருகில் இருக்கும் தட்டையான பட்டனாகும்.\n\nபவர் பட்டனை அழுத்தினால் திரை ஆஃப் ஆகும்."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"\'கைரேகை சென்சார்\' பவர் பட்டனில் உள்ளது. இது மொபைலின் விளிம்பில் சற்று மேலெழும்பிய ஒலியளவு பட்டனுக்கு அருகில் இருக்கும் தட்டையான பட்டனாகும்.\n\nபவர் பட்டனை அழுத்தினால் திரை ஆஃப் ஆகும்."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"மேலும் விருப்பங்களுக்கு மொபைலை அன்லாக் செய்யவும்"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"மேலும் விருப்பங்களுக்கு டேப்லெட்டை அன்லாக் செய்யவும்"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"மேலும் விருப்பங்களுக்குச் சாதனத்தை அன்லாக் செய்யவும்"</string>
diff --git a/packages/SystemUI/res-product/values-te/strings.xml b/packages/SystemUI/res-product/values-te/strings.xml
index 088cf883e395..e16ea11ee62d 100644
--- a/packages/SystemUI/res-product/values-te/strings.xml
+++ b/packages/SystemUI/res-product/values-te/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. కార్యాలయ ప్రొఫైల్ తీసివేయబడుతుంది, దీని వలన ప్రొఫైల్ డేటా మొత్తం తొలగించబడుతుంది."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, మీరు ఈమెయిల్‌ ఖాతాను ఉపయోగించి మీ టాబ్లెట్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, మీరు ఈమెయిల్‌ ఖాతాను ఉపయోగించి మీ ఫోన్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"వేలిముద్ర సెన్సార్ పవర్ బటన్‌పై ఉంది. ఇది టాబ్లెట్ అంచున వాల్యూమ్ పెంచడానికి ఉపయోగించే వాల్యూమ్ బటన్ పక్కన ఉన్న ఫ్లాట్ బటన్.\n\nపవర్ బటన్‌ను నొక్కితే స్క్రీన్ ఆఫ్ అవుతుంది."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"వేలిముద్ర సెన్సార్ పవర్ బటన్‌పై ఉంది. ఇది పరికరం అంచున వాల్యూమ్ పెంచడానికి ఉపయోగించే వాల్యూమ్ బటన్ పక్కన ఉన్న ఫ్లాట్ బటన్.\n\nపవర్ బటన్‌ను నొక్కితే స్క్రీన్ ఆఫ్ అవుతుంది."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"వేలిముద్ర సెన్సార్ పవర్ బటన్‌పై ఉంది. ఇది ఫోన్ అంచున వాల్యూమ్ పెంచడానికి ఉపయోగించే వాల్యూమ్ బటన్ పక్కన ఉన్న ఫ్లాట్ బటన్.\n\nపవర్ బటన్‌ను నొక్కితే స్క్రీన్ ఆఫ్ అవుతుంది."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"మరిన్ని ఆప్షన్‌ల కోసం మీ ఫోన్‌ను అన్‌లాక్ చేయండి"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"మరిన్ని ఆప్షన్‌ల కోసం మీ టాబ్లెట్‌ను అన్‌లాక్ చేయండి"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"మరిన్ని ఆప్షన్‌ల కోసం మీ పరికరాన్ని అన్‌లాక్ చేయండి"</string>
diff --git a/packages/SystemUI/res-product/values-th/strings.xml b/packages/SystemUI/res-product/values-th/strings.xml
index f367f9a93d87..b88a9f79dc9d 100644
--- a/packages/SystemUI/res-product/values-th/strings.xml
+++ b/packages/SystemUI/res-product/values-th/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้งแล้ว ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดในโปรไฟล์"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งใน <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"เซ็นเซอร์ลายนิ้วมืออยู่ที่ปุ่มเปิด/ปิด ซึ่งเป็นปุ่มแบนข้างปุ่มนูนที่ใช้ปรับระดับเสียงตรงบริเวณขอบของแท็บเล็ต\n\nการกดปุ่มเปิด/ปิดจะเป็นการปิดหน้าจอ"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"เซ็นเซอร์ลายนิ้วมืออยู่ที่ปุ่มเปิด/ปิด ซึ่งเป็นปุ่มแบนข้างปุ่มนูนที่ใช้ปรับระดับเสียงตรงบริเวณขอบของอุปกรณ์\n\nการกดปุ่มเปิด/ปิดจะเป็นการปิดหน้าจอ"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"เซ็นเซอร์ลายนิ้วมืออยู่ที่ปุ่มเปิด/ปิด ซึ่งเป็นปุ่มแบนข้างปุ่มนูนที่ใช้ปรับระดับเสียงตรงบริเวณขอบของโทรศัพท์\n\nการกดปุ่มเปิด/ปิดจะเป็นการปิดหน้าจอ"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ปลดล็อกโทรศัพท์เพื่อดูตัวเลือกเพิ่มเติม"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ปลดล็อกแท็บเล็ตเพื่อดูตัวเลือกเพิ่มเติม"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ปลดล็อกอุปกรณ์เพื่อดูตัวเลือกเพิ่มเติม"</string>
diff --git a/packages/SystemUI/res-product/values-tl/strings.xml b/packages/SystemUI/res-product/values-tl/strings.xml
index cfc6df4390e5..3ee4311c4b7f 100644
--- a/packages/SystemUI/res-product/values-tl/strings.xml
+++ b/packages/SystemUI/res-product/values-tl/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Aalisin ang profile sa trabaho, na magiging dahilan para ma-delete ang lahat ng data sa profile."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses kang nagkamali sa pagguhit ng iyong pattern sa pag-unlock. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, hihilingin sa iyong i-unlock ang tablet mo gamit ang isang email account.\n\n Subukan ulit sa loob ng <xliff:g id="NUMBER_2">%3$d</xliff:g> (na) segundo."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses kang nagkamali sa pagguhit ng iyong pattern sa pag-unlock. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, hihilingin sa iyong i-unlock ang telepono mo gamit ang isang email account.\n\n Subukan ulit sa loob ng <xliff:g id="NUMBER_2">%3$d</xliff:g> (na) segundo."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Nasa power button ang sensor para sa fingerprint. Ito ang flat na button sa tabi ng nakaangat na button ng volume sa gilid ng tablet.\n\nMamamatay ang screen kapag pinindot ang power button."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Nasa power button ang sensor para sa fingerprint. Ito ang flat na button sa tabi ng nakaangat na button ng volume sa gilid ng device.\n\nMamamatay ang screen kapag pinindot ang power button."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Nasa power button ang sensor para sa fingerprint. Ito ang flat na button sa tabi ng nakaangat na button ng volume sa gilid ng telepono.\n\nMamamatay ang screen kapag pinindot ang power button."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"I-unlock ang iyong telepono para sa higit pang opsyon"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"I-unlock ang iyong tablet para sa higit pang opsyon"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"I-unlock ang iyong device para sa higit pang opsyon"</string>
diff --git a/packages/SystemUI/res-product/values-tr/strings.xml b/packages/SystemUI/res-product/values-tr/strings.xml
index fedd3c8c1e5d..6160d6bbedbf 100644
--- a/packages/SystemUI/res-product/values-tr/strings.xml
+++ b/packages/SystemUI/res-product/values-tr/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefonun kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. İş profili kaldırılacak ve tüm profil verileri silinecektir."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı çizdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız tabletinizin kilidini bir e-posta hesabı kullanarak açmanız istenir.\n<xliff:g id="NUMBER_2">%3$d</xliff:g>\n saniye içinde tekrar deneyin."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız telefonunuzu bir e-posta hesabı kullanarak açmanız istenir.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniye içinde tekrar deneyin."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Parmak izi sensörü güç düğmesinin üzerindedir. Bu sensör, tabletin kenarındaki ses yükseltme düğmesinin yanında bulunan düz düğmedir.\n\nGüç düğmesine bastığınızda ekran kapanır."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Parmak izi sensörü güç düğmesinin üzerindedir. Bu sensör, cihazın kenarındaki ses yükseltme düğmesinin yanında bulunan düz düğmedir.\n\nGüç düğmesine bastığınızda ekran kapanır."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Parmak izi sensörü güç düğmesinin üzerindedir. Bu sensör, telefonun kenarındaki ses yükseltme düğmesinin yanında bulunan düz düğmedir.\n\nGüç düğmesine bastığınızda ekran kapanır."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Diğer seçenekler için telefonunuzun kilidini açın"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Diğer seçenekler için tabletinizin kilidini açın"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Diğer seçenekler için cihazınızın kilidini açın"</string>
diff --git a/packages/SystemUI/res-product/values-uk/strings.xml b/packages/SystemUI/res-product/values-uk/strings.xml
index 4f5fc9cf769f..3517f4e6d745 100644
--- a/packages/SystemUI/res-product/values-uk/strings.xml
+++ b/packages/SystemUI/res-product/values-uk/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER">%d</xliff:g>. Буде видалено робочий профіль і всі його дані."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі з\'явиться запит розблокувати планшет за допомогою облікового запису електронної пошти.\n\n Повторіть спробу за <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі з\'явиться запит розблокувати телефон за допомогою облікового запису електронної пошти.\n\n Повторіть спробу за <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сканер відбитків пальців розташовано на кнопці живлення. Це плоска кнопка, розташована поруч із кнопкою збільшення гучності на бічній крайці планшета.\n\nЯкщо натиснути кнопку живлення, екран вимкнеться."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сканер відбитків пальців розташовано на кнопці живлення. Це плоска кнопка, розташована поруч із кнопкою збільшення гучності на бічній крайці пристрою.\n\nЯкщо натиснути кнопку живлення, екран вимкнеться."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сканер відбитків пальців розташовано на кнопці живлення. Це плоска кнопка, розташована поруч із кнопкою збільшення гучності на бічній крайці телефона.\n\nЯкщо натиснути кнопку живлення, екран вимкнеться."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Розблокуйте телефон, щоб переглянути інші параметри"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Розблокуйте планшет, щоб переглянути інші параметри"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Розблокуйте пристрій, щоб переглянути інші параметри"</string>
diff --git a/packages/SystemUI/res-product/values-ur/strings.xml b/packages/SystemUI/res-product/values-ur/strings.xml
index ee555382b778..c6c659a1fc9a 100644
--- a/packages/SystemUI/res-product/values-ur/strings.xml
+++ b/packages/SystemUI/res-product/values-ur/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ دفتری پروفائل ہٹا دی جائے گی، جس سے پروفائل کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کر کے اپنا ٹیبلیٹ غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کر کے اپنا فون غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"فنگر پرنٹ سینسر پاور بٹن پر موجود ہے۔ یہ ٹیبلیٹ کے کنارے پر ابھرے ہوئے والیوم بٹن کے آگے والا ہموار بٹن ہے۔\n\nپاور بٹن دبانے سے اسکرین آف ہو جاتی ہے۔"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"فنگر پرنٹ سینسر پاور بٹن پر موجود ہے۔ یہ آلے کے کنارے پر ابھرے ہوئے والیوم بٹن کے آگے والا ہموار بٹن ہے۔\n\nپاور بٹن دبانے سے اسکرین آف ہو جاتی ہے۔"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"فنگر پرنٹ سینسر پاور بٹن پر موجود ہے۔ یہ فون کے کنارے پر ابھرے ہوئے والیوم بٹن کے آگے والا ہموار بٹن ہے۔\n\nپاور بٹن دبانے سے اسکرین آف ہو جاتی ہے۔"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"مزید اختیارات کے لیے اپنا فون غیر مقفل کریں"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"مزید اختیارات کے لیے اپنا ٹیبلیٹ غیر مقفل کریں"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"مزید اختیارات کے لیے اپنا آلہ غیر مقفل کریں"</string>
diff --git a/packages/SystemUI/res-product/values-uz/strings.xml b/packages/SystemUI/res-product/values-uz/strings.xml
index 58309ff3471d..c8296340e335 100644
--- a/packages/SystemUI/res-product/values-uz/strings.xml
+++ b/packages/SystemUI/res-product/values-uz/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta xato urinish qildingiz. Endi ish profili oʻchirib tashlanadi va undagi barcha maʼlumotlar ham oʻchib ketadi."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Grafik kalit <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato chizildi. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan keyin sizdan emailingizdan foydalanib, planshet qulfini ochishingiz soʻraladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan keyin yana urinib koʻring."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Grafik kalit <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato chizildi. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan keyin sizdan emailngizdan foydalanib, telefon qulfini ochishingiz soʻraladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan keyin qayta urinib koʻring."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Barmoq izi sensori quvvat tugmasida joylashgan. U tekis tugma planshetning yon chekkasida tovush balandligi tugmasining yonida joylashgan\n\nQuvvat tugmasi bosilganda ekran oʻchadi."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Barmoq izi sensori quvvat tugmasida joylashgan. U tekis tugma qurilmaning yon chekkasida tovush balandligi tugmasining yonida joylashgan.\n\nQuvvat tugmasi bosilganda ekran oʻchadi."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Barmoq izi sensori quvvat tugmasida joylashgan. U tekis tugma telefonning yon chekkasida tovush balandligi tugmasining yonida joylashgan\n\nQuvvat tugmasi bosilganda ekran oʻchadi."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Boshqa parametrlar uchun telefoningiz qulfini oching"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Boshqa parametrlar uchun planshetingiz qulfini oching"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Boshqa parametrlar uchun qurilmangiz qulfini oching"</string>
diff --git a/packages/SystemUI/res-product/values-vi/strings.xml b/packages/SystemUI/res-product/values-vi/strings.xml
index e4ecfc19bf64..e6c0388e2b47 100644
--- a/packages/SystemUI/res-product/values-vi/strings.xml
+++ b/packages/SystemUI/res-product/values-vi/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER">%d</xliff:g> lần. Hồ sơ công việc sẽ bị xóa, tức là tất cả dữ liệu hồ sơ sẽ bị xóa."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Bạn đã vẽ không chính xác hình mở khóa <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa máy tính bảng bằng tài khoản email.\n\n Hãy thử lại sau <xliff:g id="NUMBER_2">%3$d</xliff:g> giây."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Bạn đã vẽ không chính xác hình mở khóa <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa điện thoại bằng tài khoản email.\n\n Hãy thử lại sau <xliff:g id="NUMBER_2">%3$d</xliff:g> giây."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Cảm biến vân tay nằm trên nút nguồn. Đó là nút phẳng bên cạnh nút tăng âm lượng trên cạnh của máy tính bảng.\n\nKhi bạn nhấn nút nguồn, màn hình sẽ tắt."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Cảm biến vân tay nằm trên nút nguồn. Đó là nút phẳng bên cạnh nút tăng âm lượng trên cạnh của thiết bị.\n\nKhi bạn nhấn nút nguồn, màn hình sẽ tắt."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Cảm biến vân tay nằm trên nút nguồn. Đó là nút phẳng bên cạnh nút tăng âm lượng trên cạnh của điện thoại.\n\nKhi bạn nhấn nút nguồn, màn hình sẽ tắt."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Mở khóa điện thoại của bạn để xem thêm tùy chọn"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Mở khóa máy tính bảng của bạn để xem thêm tùy chọn"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Mở khóa thiết bị của bạn để xem thêm tùy chọn"</string>
diff --git a/packages/SystemUI/res-product/values-zh-rCN/strings.xml b/packages/SystemUI/res-product/values-zh-rCN/strings.xml
index 2813efd5f08d..524b11fa032d 100644
--- a/packages/SystemUI/res-product/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rCN/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。系统将移除此工作资料,而这将删除所有的工作资料数据。"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"您已 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁平板电脑。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"您已 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"指纹传感器在电源按钮上。电源按钮是一个扁平按钮,位于平板电脑边缘凸起的音量按钮旁边。\n\n按下电源按钮会关闭屏幕。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"指纹传感器在电源按钮上。电源按钮是一个扁平按钮,位于设备边缘凸起的音量按钮旁边。\n\n按下电源按钮会关闭屏幕。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"指纹传感器在电源按钮上。电源按钮是一个扁平按钮,位于手机边缘凸起的音量按钮旁边。\n\n按下电源按钮会关闭屏幕。"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"解锁手机即可查看更多选项"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"解锁平板电脑即可查看更多选项"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"解锁设备即可查看更多选项"</string>
diff --git a/packages/SystemUI/res-product/values-zh-rHK/strings.xml b/packages/SystemUI/res-product/values-zh-rHK/strings.xml
index ba07d92cda7f..ae8364dfab18 100644
--- a/packages/SystemUI/res-product/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rHK/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將移除此工作設定檔,而所有設定檔資料亦會一併刪除。"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解鎖平板電腦。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解鎖手機。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"指紋感應器位於開關按鈕上,開關按鈕形狀扁平,位於平板電腦邊緣凸起的音量按鈕旁。\n\n按下開關按鈕即可關閉螢幕。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"指紋感應器位於開關按鈕上,開關按鈕形狀扁平,位於裝置邊緣凸起的音量按鈕旁。\n\n按下開關按鈕即可關閉螢幕。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"指紋感應器位於開關按鈕上,開關按鈕形狀扁平,位於手機邊緣凸起的音量按鈕旁。\n\n按下開關按鈕即可關閉螢幕。"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"解鎖手機以存取更多選項"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"解鎖平板電腦以存取更多選項"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"解鎖裝置以存取更多選項"</string>
diff --git a/packages/SystemUI/res-product/values-zh-rTW/strings.xml b/packages/SystemUI/res-product/values-zh-rTW/strings.xml
index 736824cca2dc..ae2f72115555 100644
--- a/packages/SystemUI/res-product/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rTW/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。你的工作資料夾將遭到移除,所有設定檔資料也會一併遭到刪除。"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統會要求你透過電子郵件帳戶將平板電腦解鎖。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統會要求你透過電子郵件帳戶將手機解鎖。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"指紋感應器在電源鍵上。電源鍵形狀扁平,位於平板電腦側邊的調高音量按鈕旁。\n\n按下電源鍵可關閉螢幕。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"指紋感應器在電源鍵上。電源鍵形狀扁平,位於裝置側邊的調高音量按鈕旁。\n\n按下電源鍵可關閉螢幕。"</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"指紋感應器在電源鍵上。電源鍵形狀扁平,位於手機側邊的調高音量按鈕旁。\n\n按下電源鍵可關閉螢幕。"</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"解鎖手機可查看更多選項"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"解鎖平板電腦可查看更多選項"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"解鎖裝置可查看更多選項"</string>
diff --git a/packages/SystemUI/res-product/values-zu/strings.xml b/packages/SystemUI/res-product/values-zu/strings.xml
index dae4b22ce44c..036689b886f3 100644
--- a/packages/SystemUI/res-product/values-zu/strings.xml
+++ b/packages/SystemUI/res-product/values-zu/strings.xml
@@ -40,6 +40,9 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Iphrofayela yomsebenzi izosuswa, okuzosusa yonke idatha yephrofayela."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Udwebe ngokungalungile iphethini yakho yokuvula ngezikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphumelelanga kaningi engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuthi uvule ithebulethi yakho usebenzisa i-akhawunti ye-imeyili.\n\nZama futhi kumasekhondi angu-<xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ukulayisha ungenisa iphathini yakho yokuvula ngendlela engalungile izikhathi ezi-<xliff:g id="NUMBER_0">%1$d</xliff:g> Emva kweminye imizamo engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuvula ifoni yakho usebenzisa ukungena ngemvume ku-Google\n\n Zame futhi emumva kwengu- <xliff:g id="NUMBER_2">%3$d</xliff:g> imizuzwana."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Inzwa yesigxivizo somunwe esenkinobhweni yamandla. Yinkinobho eyisicaba eduze kwenkinobho yevolumu ephakanyisiwe emaphethelweni ethebulethi.\n\nUkucindezela inkinobho yamandla kuvala isikrini."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Inzwa yesigxivizo somunwe esenkinobhweni yamandla. Yinkinobho eyisicaba eduze kwenkinobho yevolumu ephakanyisiwe emaphethelweni edivayisi.\n\nUkucindezela inkinobho yamandla kuvala isikrini."</string>
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Inzwa yesigxivizo somunwe esenkinobhweni yamandla. Yinkinobho eyisicaba eduze kwenkinobho yevolumu ephakanyisiwe emaphethelweni efoni.\n\nUkucindezela inkinobho yamandla kuvala isikrini."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Vula ifoni yakho ukuthola okunye okungakhethwa"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Vula ithebulethi yakho ukuthola okunye okungakhethwa"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Vula idivayisi yakho ukuthola okunye okungakhethwa"</string>
diff --git a/packages/SystemUI/res-product/values/strings.xml b/packages/SystemUI/res-product/values/strings.xml
index b71caef3f593..dc6880b22830 100644
--- a/packages/SystemUI/res-product/values/strings.xml
+++ b/packages/SystemUI/res-product/values/strings.xml
@@ -122,6 +122,12 @@
Try again in <xliff:g id="number">%3$d</xliff:g> seconds.
</string>
+ <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (tablet) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.</string>
+ <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (device) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.</string>
+ <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (default) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.</string>
<!-- Text shown when viewing global actions while phone is locked and additional controls are hidden [CHAR LIMIT=NONE] -->
<string name="global_action_lock_message" product="default">Unlock your phone for more options</string>
@@ -134,4 +140,7 @@
<string name="media_transfer_playing_this_device" product="default">Playing on this phone</string>
<!-- Text informing the user that their media is now playing on this tablet device. [CHAR LIMIT=50] -->
<string name="media_transfer_playing_this_device" product="tablet">Playing on this tablet</string>
+
+
+
</resources>
diff --git a/packages/SystemUI/res/drawable/media_ttt_chip_background.xml b/packages/SystemUI/res/drawable/chipbar_background.xml
index 3abf4d72c538..57221776a32f 100644
--- a/packages/SystemUI/res/drawable/media_ttt_chip_background.xml
+++ b/packages/SystemUI/res/drawable/chipbar_background.xml
@@ -17,6 +17,6 @@
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <solid android:color="?androidprv:attr/colorSurface" />
+ <solid android:color="?androidprv:attr/colorAccentSecondary" />
<corners android:radius="32dp" />
</shape>
diff --git a/packages/SystemUI/res/drawable/media_ttt_undo_background.xml b/packages/SystemUI/res/drawable/chipbar_end_button_background.xml
index 3e2e4f055b14..80c7207a35b6 100644
--- a/packages/SystemUI/res/drawable/media_ttt_undo_background.xml
+++ b/packages/SystemUI/res/drawable/chipbar_end_button_background.xml
@@ -20,7 +20,7 @@
android:color="?android:textColorPrimary">
<item android:id="@android:id/background">
<shape>
- <solid android:color="?androidprv:attr/colorAccentPrimary"/>
+ <solid android:color="@android:color/system_accent1_200"/>
<corners android:radius="24dp" />
</shape>
</item>
diff --git a/packages/SystemUI/res/drawable/controls_panel_background.xml b/packages/SystemUI/res/drawable/controls_panel_background.xml
index 9092877fc6fa..fc108a5e1e06 100644
--- a/packages/SystemUI/res/drawable/controls_panel_background.xml
+++ b/packages/SystemUI/res/drawable/controls_panel_background.xml
@@ -18,5 +18,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#1F1F1F" />
- <corners android:radius="@dimen/notification_corner_radius" />
+ <corners android:radius="@dimen/controls_panel_corner_radius" />
</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/dream_overlay_bottom_affordance_bg.xml b/packages/SystemUI/res/drawable/dream_overlay_bottom_affordance_bg.xml
new file mode 100644
index 000000000000..3b67ddd02d78
--- /dev/null
+++ b/packages/SystemUI/res/drawable/dream_overlay_bottom_affordance_bg.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright 2023, The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorSurface"/>
+ <size
+ android:width="@dimen/dream_overlay_bottom_affordance_height"
+ android:height="@dimen/dream_overlay_bottom_affordance_width"/>
+ <corners android:radius="@dimen/dream_overlay_bottom_affordance_radius" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/ic_keyboard_backlight.xml b/packages/SystemUI/res/drawable/ic_keyboard_backlight.xml
new file mode 100644
index 000000000000..d123caf82ed5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_keyboard_backlight.xml
@@ -0,0 +1,12 @@
+<vector android:height="11dp" android:viewportHeight="12"
+ android:viewportWidth="22" android:width="20.166666dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <group>
+ <clip-path android:pathData="M0,0.5h22v11h-22z"/>
+ <path android:fillColor="#231F20" android:pathData="M6.397,9.908H0V11.5H6.397V9.908Z"/>
+ <path android:fillColor="#231F20" android:pathData="M14.199,9.908H7.801V11.5H14.199V9.908Z"/>
+ <path android:fillColor="#231F20" android:pathData="M11.858,0.5H10.142V6.434H11.858V0.5Z"/>
+ <path android:fillColor="#231F20" android:pathData="M8.348,7.129L3.885,2.975L3.823,2.932L2.668,4.003L2.621,4.046L7.084,8.2L7.146,8.243L8.301,7.172L8.348,7.129Z"/>
+ <path android:fillColor="#231F20" android:pathData="M18.224,2.975L18.177,2.932L13.653,7.129L14.807,8.2L14.854,8.243L19.379,4.046L18.224,2.975Z"/>
+ <path android:fillColor="#231F20" android:pathData="M22,9.908H15.603V11.5H22V9.908Z"/>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml b/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml
new file mode 100644
index 000000000000..2e29cae0ca4f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:inset="@dimen/qs_footer_action_inset">
+ <ripple
+ android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <!-- We make this shape a rounded rectangle instead of a oval so that it can animate -->
+ <!-- properly into an app/dialog. -->
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/white"/>
+ <corners android:radius="@dimen/qs_footer_action_corner_radius"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/qs_footer_action_corner_radius"/>
+ </shape>
+ </item>
+
+ </ripple>
+</inset> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml b/packages/SystemUI/res/drawable/qs_media_rec_scrim.xml
index 60f3cfe6dde6..de0a6201cb09 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml
+++ b/packages/SystemUI/res/drawable/qs_media_rec_scrim.xml
@@ -12,11 +12,14 @@
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
- ~ limitations under the License.
+ ~ limitations under the License
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="rectangle">
- <solid android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
- <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ android:shape="rectangle">
+ <!-- gradient from 25% in the center to 100% at edges -->
+ <gradient
+ android:type="radial"
+ android:gradientRadius="40%p"
+ android:startColor="#AE000000"
+ android:endColor="#00000000" />
</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/statusbar_chip_bg.xml b/packages/SystemUI/res/drawable/statusbar_chip_bg.xml
new file mode 100644
index 000000000000..d7de16d7c5bb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/statusbar_chip_bg.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <solid android:color="?androidprv:attr/colorAccentPrimary" />
+ <corners android:radius="@dimen/ongoing_appops_chip_bg_corner_radius" />
+</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/privacy_chip_bg.xml b/packages/SystemUI/res/drawable/statusbar_privacy_chip_bg.xml
index 99c0ab4b6220..99c0ab4b6220 100644
--- a/packages/SystemUI/res/drawable/privacy_chip_bg.xml
+++ b/packages/SystemUI/res/drawable/statusbar_privacy_chip_bg.xml
diff --git a/packages/SystemUI/res/layout/battery_status_chip.xml b/packages/SystemUI/res/layout/battery_status_chip.xml
new file mode 100644
index 000000000000..ff68ac0f9a71
--- /dev/null
+++ b/packages/SystemUI/res/layout/battery_status_chip.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_vertical|end"
+ tools:parentTag="com.android.systemui.statusbar.BatteryStatusChip">
+
+ <LinearLayout
+ android:id="@+id/rounded_container"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/ongoing_appops_chip_height"
+ android:layout_gravity="center"
+ android:background="@drawable/statusbar_chip_bg"
+ android:clipToOutline="true"
+ android:gravity="center"
+ android:maxWidth="@dimen/ongoing_appops_chip_max_width"
+ android:minWidth="@dimen/ongoing_appops_chip_min_width">
+
+ <com.android.systemui.battery.BatteryMeterView
+ android:id="@+id/battery_meter_view"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginHorizontal="10dp" />
+
+ </LinearLayout>
+</merge> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/chipbar.xml b/packages/SystemUI/res/layout/chipbar.xml
index 0ff944c2becf..a3171784903f 100644
--- a/packages/SystemUI/res/layout/chipbar.xml
+++ b/packages/SystemUI/res/layout/chipbar.xml
@@ -29,8 +29,8 @@
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:padding="@dimen/media_ttt_chip_outer_padding"
- android:background="@drawable/media_ttt_chip_background"
+ android:padding="@dimen/chipbar_outer_padding"
+ android:background="@drawable/chipbar_background"
android:layout_marginTop="20dp"
android:layout_marginStart="@dimen/notification_side_paddings"
android:layout_marginEnd="@dimen/notification_side_paddings"
@@ -43,8 +43,8 @@
<com.android.internal.widget.CachingIconView
android:id="@+id/start_icon"
- android:layout_width="@dimen/media_ttt_app_icon_size"
- android:layout_height="@dimen/media_ttt_app_icon_size"
+ android:layout_width="@dimen/chipbar_start_icon_size"
+ android:layout_height="@dimen/chipbar_start_icon_size"
android:layout_marginEnd="12dp"
android:alpha="0.0"
/>
@@ -54,47 +54,46 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:textSize="@dimen/media_ttt_text_size"
- android:textColor="?android:attr/textColorPrimary"
+ android:textSize="@dimen/chipbar_text_size"
+ android:textColor="@android:color/system_accent2_900"
android:alpha="0.0"
/>
<!-- At most one of [loading, failure_icon, undo] will be visible at a time. -->
<ImageView
android:id="@+id/loading"
- android:layout_width="@dimen/media_ttt_status_icon_size"
- android:layout_height="@dimen/media_ttt_status_icon_size"
- android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
+ android:layout_width="@dimen/chipbar_end_icon_size"
+ android:layout_height="@dimen/chipbar_end_icon_size"
+ android:layout_marginStart="@dimen/chipbar_end_item_start_margin"
android:src="@drawable/ic_progress_activity"
- android:tint="?androidprv:attr/colorAccentPrimaryVariant"
+ android:tint="@android:color/system_accent2_700"
android:alpha="0.0"
/>
<ImageView
android:id="@+id/error"
- android:layout_width="@dimen/media_ttt_status_icon_size"
- android:layout_height="@dimen/media_ttt_status_icon_size"
- android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
+ android:layout_width="@dimen/chipbar_end_icon_size"
+ android:layout_height="@dimen/chipbar_end_icon_size"
+ android:layout_marginStart="@dimen/chipbar_end_item_start_margin"
android:src="@drawable/ic_warning"
- android:tint="@color/GM2_red_500"
+ android:tint="@color/GM2_red_600"
android:alpha="0.0"
/>
- <!-- TODO(b/245610654): Re-name all the media-specific dimens to chipbar dimens instead. -->
<TextView
android:id="@+id/end_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?androidprv:attr/textColorOnAccent"
- android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
- android:textSize="@dimen/media_ttt_text_size"
- android:paddingStart="@dimen/media_ttt_chip_outer_padding"
- android:paddingEnd="@dimen/media_ttt_chip_outer_padding"
- android:paddingTop="@dimen/media_ttt_undo_button_vertical_padding"
- android:paddingBottom="@dimen/media_ttt_undo_button_vertical_padding"
- android:layout_marginTop="@dimen/media_ttt_undo_button_vertical_negative_margin"
- android:layout_marginBottom="@dimen/media_ttt_undo_button_vertical_negative_margin"
- android:background="@drawable/media_ttt_undo_background"
+ android:layout_marginStart="@dimen/chipbar_end_item_start_margin"
+ android:textSize="@dimen/chipbar_text_size"
+ android:paddingStart="@dimen/chipbar_outer_padding"
+ android:paddingEnd="@dimen/chipbar_outer_padding"
+ android:paddingTop="@dimen/chipbar_end_button_vertical_padding"
+ android:paddingBottom="@dimen/chipbar_end_button_vertical_padding"
+ android:layout_marginTop="@dimen/chipbar_end_button_vertical_negative_margin"
+ android:layout_marginBottom="@dimen/chipbar_end_button_vertical_negative_margin"
+ android:background="@drawable/chipbar_end_button_background"
android:alpha="0.0"
/>
diff --git a/packages/SystemUI/res/layout/combined_qs_header.xml b/packages/SystemUI/res/layout/combined_qs_header.xml
index d68982876448..dffe40b8454a 100644
--- a/packages/SystemUI/res/layout/combined_qs_header.xml
+++ b/packages/SystemUI/res/layout/combined_qs_header.xml
@@ -141,11 +141,14 @@
android:layout_width="wrap_content"
android:layout_height="@dimen/large_screen_shade_header_min_height"
android:gravity="center"
- app:layout_constraintEnd_toEndOf="@id/end_guide"
- app:layout_constraintTop_toTopOf="@id/date"
app:layout_constraintBottom_toBottomOf="@id/date"
- >
- <include layout="@layout/ongoing_privacy_chip"/>
+ app:layout_constraintEnd_toEndOf="@id/end_guide"
+ app:layout_constraintTop_toTopOf="@id/date">
+
+ <com.android.systemui.privacy.OngoingPrivacyChip
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent" />
+
</FrameLayout>
</com.android.systemui.util.NoRemeasureMotionLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_fullscreen.xml b/packages/SystemUI/res/layout/controls_fullscreen.xml
index e08e63b39e59..fa703038cc7e 100644
--- a/packages/SystemUI/res/layout/controls_fullscreen.xml
+++ b/packages/SystemUI/res/layout/controls_fullscreen.xml
@@ -15,19 +15,11 @@
limitations under the License.
-->
-<FrameLayout
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/control_detail_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
-
- <LinearLayout
- android:id="@+id/global_actions_controls"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:paddingHorizontal="@dimen/controls_padding_horizontal" />
-
-</FrameLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
index aa211bf8cfdc..71561c07ebd3 100644
--- a/packages/SystemUI/res/layout/controls_with_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -13,82 +13,94 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<merge
- xmlns:android="http://schemas.android.com/apk/res/android">
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:orientation="vertical"
+ tools:parentTag="android.widget.LinearLayout">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_marginBottom="@dimen/controls_header_bottom_margin">
-
- <!-- make sure the header stays centered in the layout by adding a spacer -->
- <Space
- android:id="@+id/controls_spacer"
- android:layout_width="@dimen/controls_header_menu_size"
- android:layout_height="1dp"
- android:visibility="gone" />
-
- <ImageView
- android:id="@+id/controls_close"
- android:contentDescription="@string/accessibility_desc_close"
- android:src="@drawable/ic_close"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:tint="@color/control_primary_text"
- android:layout_width="@dimen/controls_header_menu_size"
- android:layout_height="@dimen/controls_header_menu_size"
- android:padding="12dp"
- android:visibility="gone" />
- <!-- need to keep this outer view in order to have a correctly sized anchor
- for the dropdown menu, as well as dropdown background in the right place -->
<LinearLayout
- android:id="@+id/controls_header"
- android:orientation="horizontal"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:minHeight="48dp"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:gravity="center">
- <TextView
- style="@style/Control.Spinner.Header"
- android:clickable="false"
- android:id="@+id/app_or_structure_spinner"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center" />
+ android:paddingHorizontal="@dimen/controls_header_horizontal_padding"
+ android:layout_marginBottom="@dimen/controls_header_bottom_margin"
+ android:orientation="horizontal">
+
+ <!-- make sure the header stays centered in the layout by adding a spacer -->
+ <Space
+ android:id="@+id/controls_spacer"
+ android:layout_width="@dimen/controls_header_menu_button_size"
+ android:layout_height="1dp"
+ android:visibility="gone" />
+
+ <ImageView
+ android:id="@+id/controls_close"
+ android:layout_width="@dimen/controls_header_menu_button_size"
+ android:layout_height="@dimen/controls_header_menu_button_size"
+ android:layout_gravity="center_vertical"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/accessibility_desc_close"
+ android:padding="12dp"
+ android:src="@drawable/ic_close"
+ android:tint="@color/control_primary_text"
+ android:visibility="gone"
+ tools:visibility="visible" />
+
+ <!-- need to keep this outer view in order to have a correctly sized anchor
+ for the dropdown menu, as well as dropdown background in the right place -->
+ <LinearLayout
+ android:id="@+id/controls_header"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:minHeight="48dp"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/app_or_structure_spinner"
+ style="@style/Control.Spinner.Header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:clickable="false"
+ tools:text="Test app" />
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/controls_more"
+ android:layout_width="@dimen/controls_header_menu_button_size"
+ android:layout_height="@dimen/controls_header_menu_button_size"
+ android:layout_gravity="center_vertical"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/accessibility_menu"
+ android:padding="12dp"
+ android:src="@drawable/ic_more_vert"
+ android:tint="@color/control_more_vert" />
</LinearLayout>
- <ImageView
- android:id="@+id/controls_more"
- android:src="@drawable/ic_more_vert"
- android:layout_width="@dimen/controls_header_menu_size"
- android:layout_height="@dimen/controls_header_menu_size"
- android:padding="12dp"
- android:tint="@color/control_more_vert"
- android:layout_gravity="center"
- android:contentDescription="@string/accessibility_menu"
- android:background="?android:attr/selectableItemBackgroundBorderless" />
- </LinearLayout>
- <ScrollView
+ <ScrollView
android:id="@+id/controls_scroll_view"
android:layout_width="match_parent"
android:layout_height="0dp"
+ android:layout_marginHorizontal="@dimen/controls_content_margin_horizontal"
android:layout_weight="1"
- android:orientation="vertical"
android:clipChildren="true"
+ android:orientation="vertical"
android:paddingHorizontal="16dp"
android:scrollbars="none">
- <include layout="@layout/global_actions_controls_list_view" />
- </ScrollView>
+ <include layout="@layout/global_actions_controls_list_view" />
+
+ </ScrollView>
- <FrameLayout
- android:id="@+id/controls_panel"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:background="@drawable/controls_panel_background"
- android:visibility="gone"
- />
+ <FrameLayout
+ android:id="@+id/controls_panel"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginHorizontal="@dimen/controls_content_margin_horizontal"
+ android:layout_weight="1"
+ android:background="@drawable/controls_panel_background"
+ android:visibility="gone"
+ tools:visibility="visible" />
</merge>
diff --git a/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml b/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
index fb78b49dfcc2..5b2ec483f50e 100644
--- a/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
@@ -22,13 +22,14 @@
<com.android.systemui.animation.view.LaunchableImageView
android:id="@+id/home_controls_chip"
- android:layout_height="@dimen/keyguard_affordance_fixed_height"
- android:layout_width="@dimen/keyguard_affordance_fixed_width"
+ android:layout_height="@dimen/dream_overlay_bottom_affordance_height"
+ android:layout_width="@dimen/dream_overlay_bottom_affordance_width"
android:layout_gravity="bottom|start"
- android:scaleType="center"
+ android:padding="@dimen/dream_overlay_bottom_affordance_padding"
+ android:background="@drawable/dream_overlay_bottom_affordance_bg"
+ android:scaleType="fitCenter"
android:tint="?android:attr/textColorPrimary"
android:src="@drawable/controls_icon"
- android:background="@drawable/keyguard_bottom_affordance_bg"
android:contentDescription="@string/quick_controls_title" />
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/large_screen_shade_header.xml b/packages/SystemUI/res/layout/large_screen_shade_header.xml
deleted file mode 100644
index 3029a2777fd9..000000000000
--- a/packages/SystemUI/res/layout/large_screen_shade_header.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/split_shade_status_bar"
- android:layout_width="match_parent"
- android:layout_height="@dimen/large_screen_shade_header_height"
- android:minHeight="@dimen/large_screen_shade_header_min_height"
- android:clickable="false"
- android:focusable="true"
- android:paddingLeft="@dimen/large_screen_shade_header_left_padding"
- android:paddingRight="@dimen/qs_panel_padding"
- android:visibility="gone"
- android:theme="@style/Theme.SystemUI.QuickSettings.Header">
-
- <com.android.systemui.statusbar.policy.Clock
- android:id="@+id/clock"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:minWidth="48dp"
- android:minHeight="@dimen/large_screen_shade_header_min_height"
- android:gravity="start|center_vertical"
- android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
- android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Status" />
-
- <com.android.systemui.statusbar.policy.DateView
- android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start|center_vertical"
- android:gravity="center_vertical"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Status"
- systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
-
- <FrameLayout
- android:id="@+id/rightLayout"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="end">
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="end|center_vertical">
-
- <include
- android:id="@+id/carrier_group"
- layout="@layout/qs_carrier_group"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="end|center_vertical"
- android:layout_marginStart="8dp"
- android:focusable="false"
- android:minHeight="@dimen/large_screen_shade_header_min_height"
- android:minWidth="48dp" />
-
- <com.android.systemui.statusbar.phone.StatusIconContainer
- android:id="@+id/statusIcons"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingEnd="@dimen/signal_cluster_battery_padding" />
-
- <com.android.systemui.battery.BatteryMeterView
- android:id="@+id/batteryRemainingIcon"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- systemui:textAppearance="@style/TextAppearance.QS.Status" />
- <FrameLayout
- android:id="@+id/privacy_container"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:minHeight="48dp"
- android:layout_weight="1"
- android:paddingStart="16dp">
-
- <include layout="@layout/ongoing_privacy_chip" />
-
- </FrameLayout>
- </LinearLayout>
- </FrameLayout>
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/media_recommendation_view.xml b/packages/SystemUI/res/layout/media_recommendation_view.xml
index c54c4e48d13d..a4aeba1dbcd6 100644
--- a/packages/SystemUI/res/layout/media_recommendation_view.xml
+++ b/packages/SystemUI/res/layout/media_recommendation_view.xml
@@ -22,9 +22,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:translationZ="0dp"
- android:scaleType="centerCrop"
+ android:scaleType="matrix"
android:adjustViewBounds="true"
android:clipToOutline="true"
+ android:layerType="hardware"
android:background="@drawable/bg_smartspace_media_item"/>
<!-- App icon -->
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index d1a2cf4c24b2..2c7467d726b4 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -16,16 +16,15 @@
-->
-<com.android.systemui.privacy.OngoingPrivacyChip
- xmlns:android="http://schemas.android.com/apk/res/android"
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/privacy_chip"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical|end"
- android:focusable="true"
android:clipChildren="false"
android:clipToPadding="false"
- android:paddingStart="8dp"
+ tools:parentTag="com.android.systemui.privacy.OngoingPrivacyChip">
>
<LinearLayout
@@ -35,8 +34,9 @@
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:gravity="center"
+ android:clipToOutline="true"
+ android:clipToPadding="false"
android:layout_gravity="center"
android:minWidth="@dimen/ongoing_appops_chip_min_width"
- android:maxWidth="@dimen/ongoing_appops_chip_max_width"
- />
-</com.android.systemui.privacy.OngoingPrivacyChip> \ No newline at end of file
+ android:maxWidth="@dimen/ongoing_appops_chip_max_width" />
+</merge> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index b1d3ed05333b..745cfc6c1655 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -64,7 +64,7 @@
android:layout_width="@dimen/qs_footer_action_button_size"
android:layout_height="@dimen/qs_footer_action_button_size"
android:layout_gravity="center_vertical|end"
- android:background="?android:attr/selectableItemBackground"
+ android:background="@drawable/qs_footer_edit_circle"
android:clickable="true"
android:contentDescription="@string/accessibility_quick_settings_edit"
android:focusable="true"
diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
deleted file mode 100644
index 542a1c9d22bd..000000000000
--- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/quick_qs_status_icons"
- android:layout_width="match_parent"
- android:layout_height="@*android:dimen/quick_qs_offset_height"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:minHeight="@dimen/qs_header_row_min_height"
- android:clickable="false"
- android:focusable="true"
- android:theme="@style/Theme.SystemUI.QuickSettings.Header">
-
- <LinearLayout
- android:id="@+id/clock_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:layout_gravity="center_vertical|start"
- android:gravity="center_vertical|start"
- >
-
- <com.android.systemui.statusbar.policy.Clock
- android:id="@+id/clock"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:minHeight="@dimen/qs_header_row_min_height"
- android:gravity="center_vertical|start"
- android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
- android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Status" />
-
- <com.android.systemui.statusbar.policy.VariableDateView
- android:id="@+id/date_clock"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginStart="@dimen/status_bar_left_clock_end_padding"
- android:gravity="center_vertical|start"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Status"
- systemui:longDatePattern="@string/abbrev_wday_month_day_no_year_alarm"
- systemui:shortDatePattern="@string/abbrev_month_day_no_year"
- />
- </LinearLayout>
-
- <include layout="@layout/qs_carrier_group"
- android:id="@+id/carrier_group"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:minHeight="@dimen/qs_header_row_min_height"
- android:minWidth="48dp"
- android:layout_marginStart="8dp"
- android:layout_gravity="end|center_vertical"
- android:focusable="false"/>
-
- <View
- android:id="@+id/separator"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_gravity="center"
- android:layout_marginStart="8dp"
- android:layout_marginEnd="8dp"
- android:visibility="gone"
- />
-
- <FrameLayout
- android:id="@+id/rightLayout"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="end"
- >
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="center_vertical|end"
- >
- <com.android.systemui.statusbar.phone.StatusIconContainer
- android:id="@+id/statusIcons"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingEnd="@dimen/signal_cluster_battery_padding" />
-
- <com.android.systemui.battery.BatteryMeterView
- android:id="@+id/batteryRemainingIcon"
- android:layout_height="match_parent"
- android:layout_width="0dp"
- android:layout_weight="1"
- systemui:textAppearance="@style/TextAppearance.QS.Status"
- android:paddingEnd="2dp" />
-
- </LinearLayout>
- </FrameLayout>
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 9fc3f409642b..1749ed403c09 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -33,32 +33,16 @@
android:paddingStart="0dp"
android:elevation="4dp" >
- <!-- Date and privacy. Only visible in QS when not in split shade -->
- <include layout="@layout/quick_status_bar_header_date_privacy"/>
-
- <RelativeLayout
- android:id="@+id/qs_container"
+ <com.android.systemui.qs.QuickQSPanel
+ android:id="@+id/quick_qs_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="top"
+ android:layout_marginTop="@dimen/qqs_layout_margin_top"
android:clipChildren="false"
- android:clipToPadding="false">
- <!-- Time, icons and Carrier (only in QS when not in split shade) -->
- <include layout="@layout/quick_qs_status_icons"/>
-
- <com.android.systemui.qs.QuickQSPanel
- android:id="@+id/quick_qs_panel"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/quick_qs_status_icons"
- android:layout_marginTop="@dimen/qqs_layout_margin_top"
- android:accessibilityTraversalAfter="@id/quick_qs_status_icons"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:focusable="true"
- android:paddingBottom="@dimen/qqs_layout_padding_bottom"
- android:importantForAccessibility="no">
- </com.android.systemui.qs.QuickQSPanel>
- </RelativeLayout>
+ android:clipToPadding="false"
+ android:focusable="true"
+ android:paddingBottom="@dimen/qqs_layout_padding_bottom"
+ android:importantForAccessibility="no">
+ </com.android.systemui.qs.QuickQSPanel>
</com.android.systemui.qs.QuickStatusBarHeader>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
deleted file mode 100644
index 8b5d953c3fe7..000000000000
--- a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/quick_status_bar_date_privacy"
- android:layout_width="match_parent"
- android:layout_height="@*android:dimen/quick_qs_offset_height"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:gravity="center"
- android:layout_gravity="top"
- android:orientation="horizontal"
- android:importantForAccessibility="no"
- android:clickable="true"
- android:minHeight="48dp">
-
- <FrameLayout
- android:id="@+id/date_container"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:minHeight="48dp"
- android:layout_weight="1"
- android:gravity="center_vertical|start" >
-
- <com.android.systemui.statusbar.policy.VariableDateView
- android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start|center_vertical"
- android:gravity="center_vertical"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Status"
- systemui:longDatePattern="@string/abbrev_wday_month_day_no_year_alarm"
- systemui:shortDatePattern="@string/abbrev_month_day_no_year"
- />
- </FrameLayout>
-
- <!-- We want this to be centered (to align with notches). In order to do that, the following
- has to hold (in portrait):
- * date_container and privacy_container must have the same width and weight
- -->
- <android.widget.Space
- android:id="@+id/space"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_gravity="center_vertical|center_horizontal"
- android:visibility="gone" />
-
- <FrameLayout
- android:id="@+id/privacy_container"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:minHeight="48dp"
- android:layout_weight="1"
- android:gravity="center_vertical|end" >
-
- <include layout="@layout/ongoing_privacy_chip" />
-
- </FrameLayout>
-</LinearLayout>
diff --git a/packages/SystemUI/res/raw/biometricprompt_rear_landscape_base.json b/packages/SystemUI/res/raw/biometricprompt_rear_landscape_base.json
new file mode 100644
index 000000000000..49c1c40f7f4f
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_rear_landscape_base.json
@@ -0,0 +1 @@
+{"v":"5.8.1","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"BiometricPrompt_Rear_Landscape_Base_Foldable","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 18","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[169.478,169.749,0],"ix":2,"l":2},"a":{"a":0,"k":[-48.123,-30.19,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".grey400","cl":"grey400","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"black circle matte","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey904","cl":"grey904","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,35.536,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-2.552,0.087],[0,0]],"o":[[0,0],[0,-3.287],[0,0],[0,0]],"v":[[-2.301,8.869],[-2.301,-3.772],[2.301,-9.806],[2.301,9.806]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"black circle matte 2","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".blue401","cl":"blue401","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,-27.655,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,3.286],[0,0],[-2.552,0.086],[0,0]],"o":[[0,0],[0,-3.286],[0,0],[-2.552,-0.086]],"v":[[-2.301,16.282],[-2.301,-16.281],[2.301,-22.313],[2.301,22.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"black circle matte 3","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-129,"s":[-67]},{"t":-29,"s":[0]}],"ix":10},"p":{"a":0,"k":[-75.352,41.307,0],"ix":2,"l":2},"a":{"a":0,"k":[94.648,211.307,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[6.72,-5.642],[0,0],[-9.394,-0.562],[-0.298,-0.038]],"o":[[-5.153,4.329],[3.882,-16.05],[0.31,0.019],[-0.044,0.75]],"v":[[0.863,12.222],[-8.931,14.755],[8.005,-15.108],[8.931,-15.021]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[81.486,130.081],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 9","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.459,6.045],[-5.153,4.329],[-0.044,0.75],[3.116,-24.664],[5.23,-22.052],[8.666,11.92],[-2.9,9.135]],"o":[[0,0],[6.72,-5.642],[12.723,1.335],[-2.369,18.762],[-13.993,-5.333],[2.255,-5.502],[1.843,-5.815]],"v":[[-9.99,-18.348],[-0.196,-20.881],[7.872,-48.124],[21.578,-9.331],[12.104,48.124],[-22.574,21.555],[-14.791,-0.206]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[82.545,163.184],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 8","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"black circle matte 4","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey903","cl":"grey903","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18.345,-92.442,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[24.07,0],[0,0],[-8.27,0],[0,0]],"o":[[0,0],[0,8.269],[0,0],[-14.024,-17.379]],"v":[[-29.778,-14.252],[-29.778,-0.721],[-14.805,14.252],[29.778,14.252]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"black circle matte 5","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".grey902","cl":"grey902","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.947,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[154.053,139.81,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.3,0.367],[0,0],[-2.364,0.157],[0,0]],"o":[[0,0],[2.3,-0.367],[0,0],[-2.364,-0.157]],"v":[[-3.5,75.533],[-3.5,-75.533],[3.5,-76.312],[3.5,76.312]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[113.225,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 7","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,8.269],[0,0],[2.181,-0.187],[0,0],[-2.23,0],[0,42.252],[10.593,13.127],[0,0]],"o":[[0,0],[-2.23,0],[0,0],[2.181,0.187],[42.252,0],[0,-18.182],[0,0],[-8.27,0]],"v":[[-34.946,-62.973],[-34.946,-76.504],[-41.558,-76.201],[-41.558,76.201],[-34.946,76.504],[41.558,0],[24.61,-48],[-19.973,-48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[156.824,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 5","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".black 2","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-48.123,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":-129,"s":[0,0,100]},{"t":-79,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".grey700","cl":"grey700","parent":15,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-56.481,-59.936,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.767,0],[0,0],[0,-3.767],[0,0],[-3.767,0],[0,0],[0,3.767],[0,0]],"o":[[0,0],[-3.767,0],[0,0],[0,3.767],[0,0],[3.767,0],[0,0],[0,-3.767]],"v":[[46.055,-14.479],[-46.056,-14.479],[-52.876,-7.659],[-52.876,7.658],[-46.056,14.479],[46.055,14.479],[52.876,7.658],[52.876,-7.659]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".grey901","cl":"grey901","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.485,2.727,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.184,0],[0,0],[0,0],[0,0],[0,-4.375]],"o":[[0,4.184],[0,0],[0,0],[0,0],[4.375,0],[0,0]],"v":[[114.116,92.129],[106.54,99.705],[7.788,99.705],[7.788,-99.704],[106.161,-99.704],[114.116,-91.749]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[5.707,0],[0,0],[1.894,-1.05],[0.886,0.346],[0,0],[2.166,0],[0,0],[0,-5.707],[0,0],[0,-1.46],[0,0],[-1.133,-0.038],[0,0],[0,-1.459],[0,0],[-1.133,-0.038],[0,0],[-5.708,0],[0,0],[-1.894,1.05],[-0.846,-0.289],[0,0],[-2.166,0],[0,0],[0,5.706],[0,0]],"o":[[0,0],[-2.166,0],[-0.883,0.354],[0,0],[-1.895,-1.05],[0,0],[-5.708,0],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[0,5.707],[0,0],[2.165,0],[0.833,-0.334],[0,0],[1.894,1.05],[0,0],[5.707,0],[0,0],[0,-5.707]],"v":[[106.16,-102.082],[8.455,-102.082],[2.265,-100.48],[-0.488,-100.468],[-0.519,-100.48],[-6.71,-102.082],[-104.116,-102.082],[-114.45,-91.748],[-114.45,-36.119],[-116.494,-33.44],[-116.494,-18.979],[-114.45,-16.3],[-114.45,-0.877],[-116.494,1.802],[-116.494,28.704],[-114.45,31.383],[-114.45,91.749],[-104.116,102.083],[-6.495,102.083],[-0.305,100.481],[2.294,100.425],[2.395,100.481],[9.872,102.083],[106.161,102.083],[116.494,91.75],[116.494,-91.748]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.529411792755,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]} \ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_rear_portrait_base.json b/packages/SystemUI/res/raw/biometricprompt_rear_portrait_base.json
new file mode 100644
index 000000000000..9ea0d35e1de2
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_rear_portrait_base.json
@@ -0,0 +1 @@
+{"v":"5.8.1","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"BiometricPrompt_Rear_Portrait_Base_Foldable","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 18","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[169.478,169.749,0],"ix":2,"l":2},"a":{"a":0,"k":[-48.123,-30.19,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".grey400","cl":"grey400","parent":14,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"black circle matte","parent":14,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey904","cl":"grey904","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,35.536,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-2.552,0.087],[0,0]],"o":[[0,0],[0,-3.287],[0,0],[0,0]],"v":[[-2.301,8.869],[-2.301,-3.772],[2.301,-9.806],[2.301,9.806]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"black circle matte 2","parent":14,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".blue401","cl":"blue401","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,-27.655,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,3.286],[0,0],[-2.552,0.086],[0,0]],"o":[[0,0],[0,-3.286],[0,0],[-2.552,-0.086]],"v":[[-2.301,16.282],[-2.301,-16.281],[2.301,-22.313],[2.301,22.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"black circle matte 3","parent":14,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Finger 3","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-2,"ix":10},"p":{"a":0,"k":[260.134,83.782,0],"ix":2,"l":2},"a":{"a":0,"k":[302.634,38.782,0],"ix":1,"l":2},"s":{"a":0,"k":[178,178,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.262,5.076],[0,0],[-0.424,-7.095],[-0.028,-0.225]],"o":[[3.269,-3.892],[-12.123,2.932],[0.015,0.234],[0.567,-0.034]],"v":[[9.232,0.652],[11.145,-6.746],[-11.412,6.046],[-11.346,6.746]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[241.281,55.033],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 5","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[4.565,-1.102],[3.269,-3.892],[0.566,-0.033],[-18.63,2.353],[-16.656,3.951],[9.004,6.546],[6.9,-2.19]],"o":[[0,0],[-4.262,5.076],[1.008,9.61],[14.171,-1.79],[-4.028,-10.569],[-4.156,1.703],[-4.392,1.392]],"v":[[-13.858,-7.546],[-15.771,-0.148],[-36.349,5.946],[-7.047,16.299],[36.349,9.142],[16.281,-17.051],[-0.156,-11.172]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[266.285,55.833],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 4","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"black circle matte 4","parent":14,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".grey903","cl":"grey903","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18.345,-92.442,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[24.07,0],[0,0],[-8.27,0],[0,0]],"o":[[0,0],[0,8.269],[0,0],[-14.024,-17.379]],"v":[[-29.778,-14.252],[-29.778,-0.721],[-14.805,14.252],[29.778,14.252]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"black circle matte 5","parent":14,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".grey902","cl":"grey902","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.947,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[154.053,139.81,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.3,0.367],[0,0],[-2.364,0.157],[0,0]],"o":[[0,0],[2.3,-0.367],[0,0],[-2.364,-0.157]],"v":[[-3.5,75.533],[-3.5,-75.533],[3.5,-76.312],[3.5,76.312]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[113.225,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 7","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,8.269],[0,0],[2.181,-0.187],[0,0],[-2.23,0],[0,42.252],[10.593,13.127],[0,0]],"o":[[0,0],[-2.23,0],[0,0],[2.181,0.187],[42.252,0],[0,-18.182],[0,0],[-8.27,0]],"v":[[-34.946,-62.973],[-34.946,-76.504],[-41.558,-76.201],[-41.558,76.201],[-34.946,76.504],[41.558,0],[24.61,-48],[-19.973,-48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[156.824,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 5","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".black 2","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-48.123,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":-129,"s":[0,0,100]},{"t":-79,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".grey700","cl":"grey700","parent":16,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-56.481,-59.936,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.767,0],[0,0],[0,-3.767],[0,0],[-3.767,0],[0,0],[0,3.767],[0,0]],"o":[[0,0],[-3.767,0],[0,0],[0,3.767],[0,0],[3.767,0],[0,0],[0,-3.767]],"v":[[46.055,-14.479],[-46.056,-14.479],[-52.876,-7.659],[-52.876,7.658],[-46.056,14.479],[46.055,14.479],[52.876,7.658],[52.876,-7.659]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".grey901","cl":"grey901","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.485,2.727,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.184,0],[0,0],[0,0],[0,0],[0,-4.375]],"o":[[0,4.184],[0,0],[0,0],[0,0],[4.375,0],[0,0]],"v":[[114.116,92.129],[106.54,99.705],[7.788,99.705],[7.788,-99.704],[106.161,-99.704],[114.116,-91.749]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[5.707,0],[0,0],[1.894,-1.05],[0.886,0.346],[0,0],[2.166,0],[0,0],[0,-5.707],[0,0],[0,-1.46],[0,0],[-1.133,-0.038],[0,0],[0,-1.459],[0,0],[-1.133,-0.038],[0,0],[-5.708,0],[0,0],[-1.894,1.05],[-0.846,-0.289],[0,0],[-2.166,0],[0,0],[0,5.706],[0,0]],"o":[[0,0],[-2.166,0],[-0.883,0.354],[0,0],[-1.895,-1.05],[0,0],[-5.708,0],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[0,5.707],[0,0],[2.165,0],[0.833,-0.334],[0,0],[1.894,1.05],[0,0],[5.707,0],[0,0],[0,-5.707]],"v":[[106.16,-102.082],[8.455,-102.082],[2.265,-100.48],[-0.488,-100.468],[-0.519,-100.48],[-6.71,-102.082],[-104.116,-102.082],[-114.45,-91.748],[-114.45,-36.119],[-116.494,-33.44],[-116.494,-18.979],[-114.45,-16.3],[-114.45,-0.877],[-116.494,1.802],[-116.494,28.704],[-114.45,31.383],[-114.45,91.749],[-104.116,102.083],[-6.495,102.083],[-0.305,100.481],[2.294,100.425],[2.395,100.481],[9.872,102.083],[106.161,102.083],[116.494,91.75],[116.494,-91.748]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.529411792755,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]} \ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_rear_portrait_reverse_base.json b/packages/SystemUI/res/raw/biometricprompt_rear_portrait_reverse_base.json
new file mode 100644
index 000000000000..f2b259335034
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_rear_portrait_reverse_base.json
@@ -0,0 +1 @@
+{"v":"5.8.1","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"BiometricPrompt_Rear_Portrait_Reverse_Base_Foldable","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 18","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":270,"ix":10},"p":{"a":0,"k":[169.478,169.749,0],"ix":2,"l":2},"a":{"a":0,"k":[-48.123,-30.19,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".grey400","cl":"grey400","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"black circle matte","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey904","cl":"grey904","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,35.536,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-2.552,0.087],[0,0]],"o":[[0,0],[0,-3.287],[0,0],[0,0]],"v":[[-2.301,8.869],[-2.301,-3.772],[2.301,-9.806],[2.301,9.806]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"black circle matte 2","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".blue401","cl":"blue401","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,-27.655,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,3.286],[0,0],[-2.552,0.086],[0,0]],"o":[[0,0],[0,-3.286],[0,0],[-2.552,-0.086]],"v":[[-2.301,16.282],[-2.301,-16.281],[2.301,-22.313],[2.301,22.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"black circle matte 3","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-75.352,41.307,0],"ix":2,"l":2},"a":{"a":0,"k":[94.648,211.307,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[6.72,-5.642],[0,0],[-9.394,-0.562],[-0.298,-0.038]],"o":[[-5.153,4.329],[3.882,-16.05],[0.31,0.019],[-0.044,0.75]],"v":[[0.863,12.222],[-8.931,14.755],[8.005,-15.108],[8.931,-15.021]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[81.486,130.081],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 9","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.459,6.045],[-5.153,4.329],[-0.044,0.75],[3.116,-24.664],[5.23,-22.052],[8.666,11.92],[-2.9,9.135]],"o":[[0,0],[6.72,-5.642],[12.723,1.335],[-2.369,18.762],[-13.993,-5.333],[2.255,-5.502],[1.843,-5.815]],"v":[[-9.99,-18.348],[-0.196,-20.881],[7.872,-48.124],[21.578,-9.331],[12.104,48.124],[-22.574,21.555],[-14.791,-0.206]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[82.545,163.184],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 8","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"black circle matte 4","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey903","cl":"grey903","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18.345,-92.442,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[24.07,0],[0,0],[-8.27,0],[0,0]],"o":[[0,0],[0,8.269],[0,0],[-14.024,-17.379]],"v":[[-29.778,-14.252],[-29.778,-0.721],[-14.805,14.252],[29.778,14.252]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"black circle matte 5","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".grey902","cl":"grey902","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.947,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[154.053,139.81,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.3,0.367],[0,0],[-2.364,0.157],[0,0]],"o":[[0,0],[2.3,-0.367],[0,0],[-2.364,-0.157]],"v":[[-3.5,75.533],[-3.5,-75.533],[3.5,-76.312],[3.5,76.312]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[113.225,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 7","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,8.269],[0,0],[2.181,-0.187],[0,0],[-2.23,0],[0,42.252],[10.593,13.127],[0,0]],"o":[[0,0],[-2.23,0],[0,0],[2.181,0.187],[42.252,0],[0,-18.182],[0,0],[-8.27,0]],"v":[[-34.946,-62.973],[-34.946,-76.504],[-41.558,-76.201],[-41.558,76.201],[-34.946,76.504],[41.558,0],[24.61,-48],[-19.973,-48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[156.824,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 5","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".black 2","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-48.123,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":-129,"s":[0,0,100]},{"t":-79,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".grey700","cl":"grey700","parent":15,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-56.481,-59.936,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.767,0],[0,0],[0,-3.767],[0,0],[-3.767,0],[0,0],[0,3.767],[0,0]],"o":[[0,0],[-3.767,0],[0,0],[0,3.767],[0,0],[3.767,0],[0,0],[0,-3.767]],"v":[[46.055,-14.479],[-46.056,-14.479],[-52.876,-7.659],[-52.876,7.658],[-46.056,14.479],[46.055,14.479],[52.876,7.658],[52.876,-7.659]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".grey901","cl":"grey901","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.485,2.727,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.184,0],[0,0],[0,0],[0,0],[0,-4.375]],"o":[[0,4.184],[0,0],[0,0],[0,0],[4.375,0],[0,0]],"v":[[114.116,92.129],[106.54,99.705],[7.788,99.705],[7.788,-99.704],[106.161,-99.704],[114.116,-91.749]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[5.707,0],[0,0],[1.894,-1.05],[0.886,0.346],[0,0],[2.166,0],[0,0],[0,-5.707],[0,0],[0,-1.46],[0,0],[-1.133,-0.038],[0,0],[0,-1.459],[0,0],[-1.133,-0.038],[0,0],[-5.708,0],[0,0],[-1.894,1.05],[-0.846,-0.289],[0,0],[-2.166,0],[0,0],[0,5.706],[0,0]],"o":[[0,0],[-2.166,0],[-0.883,0.354],[0,0],[-1.895,-1.05],[0,0],[-5.708,0],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[0,5.707],[0,0],[2.165,0],[0.833,-0.334],[0,0],[1.894,1.05],[0,0],[5.707,0],[0,0],[0,-5.707]],"v":[[106.16,-102.082],[8.455,-102.082],[2.265,-100.48],[-0.488,-100.468],[-0.519,-100.48],[-6.71,-102.082],[-104.116,-102.082],[-114.45,-91.748],[-114.45,-36.119],[-116.494,-33.44],[-116.494,-18.979],[-114.45,-16.3],[-114.45,-0.877],[-116.494,1.802],[-116.494,28.704],[-114.45,31.383],[-114.45,91.749],[-104.116,102.083],[-6.495,102.083],[-0.305,100.481],[2.294,100.425],[2.395,100.481],[9.872,102.083],[106.161,102.083],[116.494,91.75],[116.494,-91.748]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.529411792755,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]} \ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index a2fa52c91f4d..3eddc0b16651 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"As jy met jou volgende poging \'n verkeerde PIN invoer, sal jou werkprofiel en die data daarvan uitgevee word."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"As jy met jou volgende poging \'n verkeerde wagwoord invoer, sal jou werkprofiel en die data daarvan uitgevee word."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Raak die vingerafdruksensor"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Vingerafdrukikoon"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Kan nie gesig herken nie. Gebruik eerder vingerafdruk."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kennisgewingskerm."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Vinnige instellings."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kitsinstellings en kennisgewingskerm."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Sluitskerm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Werksluitskerm"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Maak toe"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Helderheid"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Kleuromkering"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Kleurregstelling"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Lettergrootte"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Bestuur gebruikers"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Klaar"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Maak toe"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"skermopname"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Titelloos"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Bystandmodus"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Lettergrootte"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Maak kleiner"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Maak groter"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrotingvenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vergrotingvensterkontroles"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoem in"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrole bygevoeg.}other{# kontroles bygevoeg.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Verwyder"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Voeg <xliff:g id="APPNAME">%s</xliff:g> by?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Wanneer jy <xliff:g id="APPNAME">%s</xliff:g> byvoeg, kan dit kontroles en inhoud by hierdie paneel voeg. Jy kan in sommige apps kies watter kontroles hier verskyn."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Verwyder kontroles vir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"As gunsteling gemerk"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"As gunsteling gemerk; posisie <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"As gunsteling ontmerk"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Ander"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Voeg by toestelkontroles"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Voeg by"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Verwyder"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Voorgestel deur <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Toestel is gesluit"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Wys en beheer toestelle van sluitskerm af?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Jy kan vir jou eksterne toestelle kontroles op die sluitskerm byvoeg.\n\nJou toestelprogram kan jou dalk toelaat om sommige toestelle te beheer sonder om jou foon of tablet te ontsluit.\n\nJy kan enige tyd in Instellings veranderings maak."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Beheer toestelle van sluitskerm af?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Jy kan sommige toestelle beheer sonder om jou foon of tablet te ontsluit.\n\nJou toestelprogram bepaal watter toestelle op dié manier beheer kan word."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nee, dankie"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN bevat letters of simbole"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Voeg kontroles by"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Wysig kontroles"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Voeg app by"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Verwyder app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Voeg uitvoere by"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Groep"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 toestel gekies"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Minstens een toestel beskikbaar is"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Wissel skerms nou"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Ontvou foon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Wissel skerms?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Gebruik die agterste kamera vir hoër resolusie"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Keer die foon om vir hoër resolusie"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Voubare toestel word ontvou"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Voubare toestel word omgekeer"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batterykrag oor"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Skakel oor na werkprofiel"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Maak toe"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Sluitskerminstellings"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-fi is nie beskikbaar nie"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera is geblokkeer"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera en mikrofoon is geblokkeer"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofoon is geblokkeer"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteitmodus is aan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-af/tiles_states_strings.xml b/packages/SystemUI/res/values-af/tiles_states_strings.xml
index da24a79759f7..662aa717ffc1 100644
--- a/packages/SystemUI/res/values-af/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-af/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Af"</item>
<item msgid="5966994759929723339">"Aan"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Onbeskikbaar"</item>
+ <item msgid="2478289035899842865">"Af"</item>
+ <item msgid="5137565285664080143">"Aan"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7f2ccac9058c..9a168e158ca7 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"በሚቀጥለው ሙከራ ላይ ትክክል ያልሆነ ፒን ካስገቡ የእርስዎ የሥራ መገለጫ እና ውሂቡ ይሰረዛሉ።"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"በሚቀጥለው ሙከራ ላይ ትክክል ያልሆነ የይለፍ ቃል ካስገቡ የእርስዎ የሥራ መገለጫ እና ውሂቡ ይሰረዛሉ።"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"የጣት አሻራ ዳሳሹን ይንኩ"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"የጣት አሻራ አዶ"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"መልክን መለየት አልተቻለም። በምትኩ የጣት አሻራ ይጠቀሙ።"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"የስራ ማያ ገጽ ቁልፍ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ዝጋ"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ብሩህነት"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ተቃራኒ ቀለም"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"የቀለም ማስተካከያ"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"የቅርጸ-ቁምፊ መጠን"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ተጠቃሚዎችን ያስተዳድሩ"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ተከናውኗል"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ዝጋ"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ማያን መቅረጽ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ርዕስ የለም"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ተጠባባቂ"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"የቅርጸ-ቁምፊ መጠን"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"አሳንስ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ተለቅ አድርግ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"የማጉያ መስኮት"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"የማጉያ መስኮት መቆጣጠሪያዎች"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"አጉላ"</string>
@@ -811,7 +807,10 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ቁጥጥር ታክሏል።}one{# ቁጥጥር ታክሏል።}other{# ቁጥጥሮች ታክለዋል።}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"ተወግዷል"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ይታከል?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g>ን ሲያክሉ መቆጣጠሪያዎችን እና ይዘትን ወደዚህ ፓነል ሊያክል ይችላል። በአንዳንድ መተግበሪያዎች ውስጥ የትኛዎቹ መቆጣጠሪያዎች እዚህ ላይ እንደሚታዩ መምረጥ ይችላሉ።"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <!-- no translation found for controls_panel_remove_app_authorization (5920442084735364674) -->
+ <skip />
<string name="accessibility_control_favorite" msgid="8694362691985545985">"ተወዳጅ የተደረገ"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"ተወዳጅ ተደርጓል፣ አቋም <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ተወዳጅ አልተደረገም"</string>
@@ -829,12 +828,15 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ሌላ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ወደ የመሣሪያ መቆጣጠሪያዎች ያክሉ"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"አክል"</string>
+ <!-- no translation found for controls_dialog_remove (3775288002711561936) -->
+ <skip />
<string name="controls_dialog_message" msgid="342066938390663844">"በ<xliff:g id="APP">%s</xliff:g> የተጠቆመ"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"መሣሪያ ተቆልፏል"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ከማያ ገጽ ቆልፍ ላይ መሳሪያዎች ይታዩ እና ይቆጣጠሩ?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ለውጫዊ መሳሪያዎችዎ መቆጣጠሪያዎችን ወደ ማያ ገጽ ቆልፍ ማከል ይችላሉ።\n\nየእርስዎ መሣሪያ መተግበሪያ የእርስዎን ስልክ ወይም ጡባዊ ሳይከፍቱ አንዳንድ መሣሪያዎችን እንዲቆጣጠሩ ሊፈቅድልዎ ይችላል።\n\nበቅንብሮች ውስጥ በማንኛውም ጊዜ ለውጦችን ማድረግ ይችላሉ።"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"መሳሪያዎች ከማያ ገጽ ቆልፍ ይቆጣጠሩ?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"የእርስዎን ስልክ ወይም ጡባዊ ሳይከፍቱ አንዳንድ መሳሪያዎችን መቆጣጠር ይችላሉ።\n\nየእርስዎ መሣሪያ መተግበሪያ የትኞቹ መሣሪያዎች በዚህ መንገድ ሊቆጣጠሩ እንደሚችሉ ይወስናል።"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"አይ፣ አመሰግናለሁ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"አዎ"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ፒን ፊደሎችን ወይም ምልክቶችን ይይዛል"</string>
@@ -882,6 +884,8 @@
<string name="controls_menu_add" msgid="4447246119229920050">"መቆጣጠሪያዎችን አክል"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"መቆጣጠሪያዎችን ያርትዑ"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"መተግበሪያ አክል"</string>
+ <!-- no translation found for controls_menu_remove (3006525275966023468) -->
+ <skip />
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"ውጽዓቶችን ያክሉ"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"ቡድን"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 መሣሪያ ተመርጧል"</string>
@@ -909,10 +913,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"መሰራጨት አይችልም"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ማስቀመጥ አልተቻለም። እንደገና ይሞክሩ።"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ማስቀመጥ አልተቻለም።"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ቢያንስ 4 ቁምፊዎችን ይጠቀሙ"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ከ16 የሚያንሱ ቁምፊዎችን ይጠቀሙ"</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>
@@ -1032,16 +1034,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ቢያንስ አንድ መሣሪያ ይገኛል"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"የይንኩ እና ይያዙ አቋራጭ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ይቅር"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ማያ ገፆችን አሁን ይቀይሩ"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ስልክን ይዘርጉ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ማያ ገፆች ይቀየሩ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ለከፍተኛ ጥራት የኋላ ካሜራውን ይጠቀሙ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ለከፍተኛ ጥራት ስልኩን ይቀይሩ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"መታጠፍ የሚችል መሣሪያ እየተዘረጋ ነው"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"መታጠፍ የሚችል መሣሪያ እየተገለበጠ ነው"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ባትሪ ይቀራል"</string>
@@ -1053,4 +1050,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ወደ የሥራ መገለጫ ቀይር"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ዝጋ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"የማያ ገጽ ቁልፍ ቅንብሮች"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi አይገኝም"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ካሜራ ታግዷል"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ካሜራ እና ማይክሮፎን ታግደዋል"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ማይክሮፎን ታግዷል"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"የቅድሚያ ሁነታ በርቷል"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/tiles_states_strings.xml b/packages/SystemUI/res/values-am/tiles_states_strings.xml
index 26ef52d996ac..e5d68d985792 100644
--- a/packages/SystemUI/res/values-am/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-am/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"ጠፍቷል"</item>
<item msgid="5966994759929723339">"በርቷል"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"አይገኝም"</item>
+ <item msgid="2478289035899842865">"ጠፍቷል"</item>
+ <item msgid="5137565285664080143">"በርቷል"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 50165d4cd1f2..4726d861d755 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"عند إدخال رقم تعريف شخصي غير صحيح في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"عند إدخال كلمة مرور غير صحيحة في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"المس أداة استشعار بصمة الإصبع"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"رمز بصمة الإصبع"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"يتعذّر التعرّف على الوجه. استخدِم بصمة الإصبع بدلاً من ذلك."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"شاشة قفل بيانات العمل"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"إغلاق"</string>
@@ -237,8 +237,8 @@
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"التدوير التلقائي للشاشة"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"الموقع الجغرافي"</string>
<string name="quick_settings_screensaver_label" msgid="1495003469366524120">"شاشة الاستراحة"</string>
- <string name="quick_settings_camera_label" msgid="5612076679385269339">"الوصول إلى الكاميرا"</string>
- <string name="quick_settings_mic_label" msgid="8392773746295266375">"الوصول إلى الميكروفون"</string>
+ <string name="quick_settings_camera_label" msgid="5612076679385269339">"الكاميرا"</string>
+ <string name="quick_settings_mic_label" msgid="8392773746295266375">"الميكروفون"</string>
<string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"متاح"</string>
<string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"محظور"</string>
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"جهاز الوسائط"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"السطوع"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"قلب الألوان"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"تصحيح الألوان"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"حجم الخط"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"إدارة المستخدمين"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"تم"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"إغلاق"</string>
@@ -654,7 +653,7 @@
<string name="right_keycode" msgid="2480715509844798438">"رمز مفتاح اليمين"</string>
<string name="left_icon" msgid="5036278531966897006">"رمز اليسار"</string>
<string name="right_icon" msgid="1103955040645237425">"رمز اليمين"</string>
- <string name="drag_to_add_tiles" msgid="8933270127508303672">"اضغط باستمرار مع السحب لإضافة الميزات."</string>
+ <string name="drag_to_add_tiles" msgid="8933270127508303672">"اضغط باستمرار مع السحب لإضافة المربّعات"</string>
<string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"اضغط باستمرار مع السحب لإعادة ترتيب الميزات."</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"اسحب هنا للإزالة"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"الحدّ الأدنى من عدد المربعات الذي تحتاج إليه هو <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g>"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"تسجيل محتوى الشاشة"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"بلا عنوان"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"وضع الاستعداد"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"حجم الخط"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"تصغير الحجم"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"تكبير الحجم"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"نافذة التكبير"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"عناصر التحكم في نافذة التكبير"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"تكبير"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{تمت إضافة عنصر تحكّم واحد.}zero{تمت إضافة # عنصر تحكّم.}two{تمت إضافة عنصرَي تحكّم.}few{تمت إضافة # عناصر تحكّم.}many{تمت إضافة # عنصر تحكّم.}other{تمت إضافة # عنصر تحكّم.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"تمت الإزالة"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"هل تريد إضافة \"<xliff:g id="APPNAME">%s</xliff:g>\"؟"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"عند إضافة تطبيق \"<xliff:g id="APPNAME">%s</xliff:g>\"، يمكنه إضافة عناصر تحكّم ومحتوى إلى هذه اللوحة. في بعض التطبيقات، يمكنك اختيار عناصر التحكّم التي تظهر هنا."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"هل تريد إزالة عناصر التحكّم في \"<xliff:g id="APPNAME">%s</xliff:g>\"؟"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"تمت الإضافة إلى المفضّلة"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"تمت الإضافة إلى المفضّلة، الموضع <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"تمت الإزالة من المفضّلة"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"غير ذلك"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"إضافة إلى أدوات التحكم بالجهاز"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"إضافة"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"إزالة"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"اقتراح من <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"الجهاز مُقفل."</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"هل تريد عرض أجهزتك والتحكم فيها من شاشة القفل؟"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"يمكنك إضافة عناصر تحكم لشاشة القفل الخاصة بأجهزتك الخارجية.\n\nقد يسمح لك تطبيق الجهاز بالتحكم في بعض الأجهزة بدون فتح قفل هاتفك أو جهازك اللوحي.\n\nيمكنك إجراء التغييرات في أي وقت من الإعدادات."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"هل تريد التحكم في الأجهزة من شاشة القفل؟"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"يمكنك التحكم في بعض الأجهزة بدون فتح قفل هاتفك أو جهازك اللوحي.\n\nيحدِّد تطبيق الجهاز أيًا من الأجهزة يمكن التحكم فيه على هذا النحو."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"لا، شكرًا"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"نعم"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"يشتمل رقم التعريف الشخصي على أحرف أو رموز."</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"إضافة عناصر تحكّم"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"تعديل عناصر التحكّم"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"إضافة تطبيق"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"إزالة التطبيق"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"إضافة مخرجات"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"مجموعة"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"تم اختيار جهاز واحد."</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"يتعذّر البث"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"لا يمكن إجراء الحفظ. يُرجى إعادة المحاولة."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"لا يمكن إجراء الحفظ."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"يجب استخدام 4 أحرف على الأقل."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"يجب أن يحتوي الرمز على أقل من 16 حرفًا."</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• توفُّر جهاز واحد على الأقل"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"انقر مع الاستمرار على الاختصار."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"إلغاء"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"تبديل الشاشتَين الآن"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"فتح الهاتف"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"هل تريد تبديل الشاشتَين؟"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"للحصول على درجة دقة أعلى، استخدِم الكاميرا الخلفية."</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"للحصول على درجة دقة أعلى، اقلِب الهاتف."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"جهاز قابل للطي يجري فتحه"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"جهاز قابل للطي يجري قلبه"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"النسبة المئوية المتبقية من شحن البطارية: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"التبديل إلى الملف الشخصي للعمل"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"إغلاق"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"إعدادات شاشة القفل"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏لا يتوفّر اتصال Wi-Fi."</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"استخدام الكاميرا محظور."</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"استخدام الكاميرا والميكروفون محظور."</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"استخدام الميكروفون محظور."</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"وضع الأولوية مفعّل."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/tiles_states_strings.xml b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
index b88d09706595..31d97076ce4e 100644
--- a/packages/SystemUI/res/values-ar/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"غير مفعّلة"</item>
<item msgid="5966994759929723339">"مفعَّلة"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"الخيار غير متوفّر"</item>
+ <item msgid="2478289035899842865">"الخيار غير مفعَّل"</item>
+ <item msgid="5137565285664080143">"الخيار مفعَّل"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 2f868ec0009e..2e7eb5473cde 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল পিন দিলে, আপোনাৰ কৰ্মস্থানৰ প্ৰ’ফাইল আৰু ইয়াৰ ডেটা মচি পেলোৱা হ’ব।"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল পাছৱৰ্ড দিলে, আপোনাৰ কৰ্মস্থানৰ প্ৰ’ফাইল আৰু ইয়াৰ ডেটা মচি পেলোৱা হ’ব।"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰক"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ফিংগাৰপ্ৰিণ্ট আইকন"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"মুখাৱয়ব চিনিব নোৱাৰি। ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক।"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ লক স্ক্ৰীন"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ কৰক"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"উজ্জ্বলতা"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ৰং বিপৰীতকৰণ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ৰং শুধৰণী"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ফণ্টৰ আকাৰ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ব্যৱহাৰকাৰী পৰিচালনা কৰক"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"সম্পন্ন কৰা হ’ল"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"বন্ধ কৰক"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"স্ক্ৰীন ৰেকৰ্ডিং"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"কোনো শিৰোনাম নাই"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ষ্টেণ্ডবাই"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ফণ্টৰ আকাৰ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"সৰু কৰক"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ডাঙৰ কৰক"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"বিবৰ্ধন ৱিণ্ড’"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"বিবৰ্ধন ৱিণ্ড’ৰ নিয়ন্ত্ৰণসমূহ"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"জুম ইন কৰক"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# টা নিয়ন্ত্ৰণ যোগ দিয়া হৈছে।}one{# টা নিয়ন্ত্ৰণ যোগ দিয়া হৈছে।}other{# টা নিয়ন্ত্ৰণ যোগ দিয়া হৈছে।}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"আঁতৰোৱা হ’ল"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> যোগ দিবনে?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"আপুনি <xliff:g id="APPNAME">%s</xliff:g> যোগ দিলে, ই এই পেনেলত নিয়ন্ত্ৰণ আৰু সমল যোগ দিব পাৰে। কিছুমান এপত আপুনি কোনবোৰ নিয়ন্ত্ৰণ ইয়াত দেখা পোৱা যাব সেয়া বাছনি কৰিব পাৰে।"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g>ৰ নিয়ন্ত্ৰণ আঁতৰাবনে?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"প্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"প্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল, স্থান <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"অপ্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"অন্য"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ডিভাইচৰ নিয়ন্ত্ৰণসমূহত যোগ দিয়ক"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"যোগ দিয়ক"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"আঁতৰাওক"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g>এ পৰামৰ্শ হিচাপে আগবঢ়োৱা"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"ডিভাইচ লক হৈ আছে"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"লক স্ক্ৰীনৰ পৰা ডিভাইচসমূহ লক আৰু নিয়ন্ত্ৰণ কৰিবনে?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"আপুনি লক স্ক্ৰীনত আপোনাৰ বাহ্যিক ডিভাইচৰ বাবে নিয়ন্ত্ৰণ যোগ দিব পাৰে।\n\nআপোনাৰ ডিভাইচ এপে আপোনাক আপোনাৰ ফ’ন অথবা টেবলেট আনলক নকৰাকৈ কিছুমান ডিভাইচ নিয়ন্ত্ৰণ কৰাৰ অনুমতি দিব পাৰে। \n\nআপুনি যিকোনো সময়তে ছেটিঙত সালসলনি কৰিব পাৰে।"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"লক স্ক্ৰীনৰ পৰা ডিভাইচসমূহ নিয়ন্ত্ৰণ কৰিবনে?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"আপুনি আপোনাৰ ফ’ন অথবা টেবলেট আনলক নকৰাকৈ কিছুমান ডিভাইচ নিয়ন্ত্ৰণ কৰিব পাৰে।\n\nএইধৰণে কোনবোৰ ডিভাইচ নিয়ন্ত্ৰণ কৰিব পাৰি সেয়া আপোনাৰ ডিভাইচ এপে নিৰ্ধাৰণ কৰে।"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"নালাগে, ধন্যবাদ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"হয়"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"পিনত বৰ্ণ অথবা প্ৰতীকসমূহ থাকে"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"নিয়ন্ত্ৰণসমূহ যোগ দিয়ক"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"নিয়ন্ত্ৰণসমূহ সম্পাদনা কৰক"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"এপ্‌ যোগ দিয়ক"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"এপ্‌টো আঁতৰাওক"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"আউটপুটসমূহ যোগ দিয়ক"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"গোট"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"১ টা ডিভাইচ বাছনি কৰা হৈছে"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"সম্প্ৰচাৰ কৰিব নোৱাৰি"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ছেভ কৰিব নোৱাৰি। পুনৰ চেষ্টা কৰক।"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ছেভ কৰিব নোৱাৰি।"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"অতি কমেও ৪ টা বৰ্ণ ব্যৱহাৰ কৰক"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"১৬ টাতকৈ কম বৰ্ণ ব্যৱহাৰ কৰক"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• অতি কমেও এটা ডিভাইচ উপলব্ধ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"শ্বৰ্টকাটটোত স্পৰ্শ কৰি ধৰি ৰাখক"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"বাতিল কৰক"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"এতিয়াই স্ক্ৰীন সলনি কৰক"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ফ’নটো আনফ’ল্ড কৰক"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"স্ক্ৰীন সলনি কৰিবনে?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"অধিক ৰিজ’লিউছনৰ বাবে, পিছফালৰ কেমেৰাটো ব্যৱহাৰ কৰক"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"অধিক ৰিজ’লিউছনৰ বাবে, ফ’নটো লুটিয়াই দিয়ক"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"জপাব পৰা ডিভাইচৰ জাপ খুলি থকা হৈছে"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"জপাব পৰা ডিভাইচৰ ওলোটাই থকা হৈছে"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> বেটাৰী বাকী আছে"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"কৰ্মস্থানৰ প্ৰ’ফাইললৈ সলনি কৰক"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"বন্ধ কৰক"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"লক স্ক্ৰীনৰ ছেটিং"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ৱাই-ফাই উপলব্ধ নহয়"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"কেমেৰা অৱৰোধ কৰা আছে"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"কেমেৰা আৰু মাইক্ৰ’ফ’ন অৱৰোধ কৰা আছে"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"মাইক্ৰ’ফ’ন অৱৰোধ কৰা আছে"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"অগ্ৰাধিকাৰ দিয়া ম’ড অন আছে"</string>
</resources>
diff --git a/packages/SystemUI/res/values-as/tiles_states_strings.xml b/packages/SystemUI/res/values-as/tiles_states_strings.xml
index e7dc9b4e180a..a9c3e3b997b7 100644
--- a/packages/SystemUI/res/values-as/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-as/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"অফ আছে"</item>
<item msgid="5966994759929723339">"অন আছে"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"উপলব্ধ নহয়"</item>
+ <item msgid="2478289035899842865">"অফ আছে"</item>
+ <item msgid="5137565285664080143">"অন আছে"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index db801251a51a..084df898bc20 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Növbəti cəhddə yanlış PIN daxil etsəniz, iş profili və datası silinəcək."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Növbəti cəhddə yanlış parol daxil etsəniz, iş profili və datası silinəcək."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Barmaq izi sensoruna klikləyin"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Barmaq izi ikonası"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tanımaq olmur. Barmaq izini işlədin."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildiriş kölgəsi."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tez ayarlar."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Sürətli ayarlar və Bildiriş göstərişi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kilid ekranı."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekran kilidi"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Qapadın"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Parlaqlıq"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Rəng inversiyası"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Rəng korreksiyası"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Şrift ölçüsü"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"İstifadəçiləri idarə edin"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Hazır"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Bağlayın"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekran çəkimi"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Başlıq yoxdur"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Gözləmə rejimi"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Şrift ölçüsü"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Kiçildin"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Böyüdün"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Böyütmə Pəncərəsi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Böyütmə Pəncərəsi Kontrolları"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Yaxınlaşdırın"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# nizamlayıcı əlavə edilib.}other{# nizamlayıcı əlavə edilib.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Silinib"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> əlavə edilsin?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> əlavə etdiyiniz zaman, o, bu panelə nizamlayıcılar və məzmun əlavə edə bilər. Bəzi tətbiqlərdə burada hansı nizamlayıcıların göstərilməsini seçə bilərsiniz."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> nizamlayıcıları silinsin?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Sevimlilərə əlavə edilib"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Sevimlilərə əlavə edilib, sıra: <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Sevimlilərdən silinib"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Digər"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Cihaz idarəetmələrinə əlavə edin"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Əlavə edin"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Silin"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> tərəfindən təklif edilib"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Cihaz kilidlənib"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Kilid ekranından cihazlar göstərilsin və idarə edilsin?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Xarici cihazlarınız üçün kilid ekranına nizamlayıcılar əlavə edə bilərsiniz.\n\nCihaz tətbiqiniz sizə telefon və ya planşetinizin kilidini açmadan bəzi cihazları idarə etməyə imkan verə bilər.\n\nİstənilən vaxt Ayarlarda dəyişiklik edə bilərsiniz."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Cihazları kilid ekranından idarə etmək istəyirsiniz?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Telefon və ya planşetinizin kilidini açmadan bəzi cihazları idarə edə bilərsiniz.\n\nCihaz tətbiqiniz hansı cihazların bu şəkildə idarə oluna biləcəyini müəyyən edir."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Xeyr, təşəkkür"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Bəli"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN hərflər və ya simvollar ehtiva edir"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Vidcet əlavə edin"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Vidcetlərə düzəliş edin"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tətbiq əlavə edin"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Tətbiqi silin"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Nəticələri əlavə edin"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Qrup"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçilib"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Yayımlamaq mümkün deyil"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Ən azı 4 simvoldan istifadə edin"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Maksimum 16 simvoldan 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ən azı bir cihaz əlçatandır"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"İndi ekranları dəyişin"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Telefonu açın"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Ekranlar dəyişdirilsin?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Daha yüksək ayırdetmə dəqiqliyi üçün arxa kameradan istifadə edin"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Daha yüksək ayırdetmə dəqiqliyi üçün telefonu çevirin"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Qatlana bilən cihaz açılır"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Qatlana bilən cihaz fırladılır"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> enerji qalıb"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"İş profilinə keçin"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Bağlayın"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Kilid ekranı ayarları"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi əlçatan deyil"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera bloklanıb"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera və mikrofon bloklanıb"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon bloklanıb"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritet rejimi aktivdir"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/tiles_states_strings.xml b/packages/SystemUI/res/values-az/tiles_states_strings.xml
index e0fcf890a505..d973e4ead3c2 100644
--- a/packages/SystemUI/res/values-az/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-az/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Deaktiv"</item>
<item msgid="5966994759929723339">"Aktiv"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Əlçatan deyil"</item>
+ <item msgid="2478289035899842865">"Deaktiv"</item>
+ <item msgid="5137565285664080143">"Aktiv"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 494bcbe42aa6..50638c5ea85e 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ako unesete netačan PIN pri sledećem pokušaju, izbrisaćemo poslovni profil i njegove podatke."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ako unesete netačnu lozinku pri sledećem pokušaju, izbrisaćemo poslovni profil i njegove podatke."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dodirnite senzor za otisak prsta"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona otiska prsta"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Lice nije prepoznato. Koristite otisak prsta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Prozor sa obaveštenjima."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Brza podešavanja."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brza podešavanja i traka sa obaveštenjima."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaključan ekran."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan ekran za posao"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvori"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Osvetljenost"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzija boja"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekcija boja"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Veličina fonta"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Upravljajte korisnicima"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Gotovo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zatvori"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Započni"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Nema obaveštenja"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nema novih obaveštenja"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte da vidite starija obaveštenja"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte za starija obaveštenja"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja roditelj"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organizacija je vlasnik uređaja i može da nadgleda mrežni saobraćaj"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> je vlasnik ovog uređaja i može da nadgleda mrežni saobraćaj"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"snimanje ekrana"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje pripravnosti"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Veličina fonta"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Umanjite"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Uvećajte"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za uvećanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za uvećanje"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Uvećajte"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrola je dodata.}one{# kontrola je dodata.}few{# kontrole su dodate.}other{# kontrola je dodato.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Uklonjeno"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Želite li da dodate <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Kada dodate aplikaciju <xliff:g id="APPNAME">%s</xliff:g>, ona može da dodaje kontrole i sadržaj u ovo okno. U nekim aplikacijama možete da izaberete koje će se kontrole ovde prikazivati."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Želite da uklonite kontrole za <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Označeno je kao omiljeno"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Označeno je kao omiljeno, <xliff:g id="NUMBER">%d</xliff:g>. pozicija"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Uklonjeno je iz omiljenih"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Dodajte u kontrole uređaja"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Ukloni"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Predlaže <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Uređaj je zaključan"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Želite li da prikazujete i kontrolišete uređaje sa zaključanog ekrana?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Možete da dodate kontrole za spoljne uređaje na zaključani ekran.\n\nAplikacija na uređaju može da vam omogući da kontrolišete neke uređaje bez otključavanja telefona ili tableta.\n\nTo možete da promenite kad god želite u Podešavanjima."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Želite li da kontrolišete uređaje sa zaključanog ekrana?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Neke uređaje možete da kontrolišete bez otključavanja telefona ili tableta.\n\nAplikacija na uređaju određuje koji uređaji mogu da se kontrolišu na ovaj način."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, hvala"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Da"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN sadrži slova ili simbole"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrole"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Izmeni kontrole"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikaciju"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Ukloni aplikaciju"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajte izlaze"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Izabran je 1 uređaj"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• da je dostupan barem jedan uređaj"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Zameni ekrane"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Otvorite telefon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Želite da zamenite ekrane?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Za veću rezoluciju koristite zadnju kameru"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za veću rezoluciju obrnite telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Uređaj na preklop se otvara"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Uređaj na preklop se obrće"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Preostalo je još<xliff:g id="PERCENTAGE">%s</xliff:g> baterije"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Pređi na poslovni profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Podešavanja zaključanog ekrana"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi nije dostupan"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon su blokirani"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetni režim je uključen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
index fd604b5f079f..32051ef19743 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Isključeno"</item>
<item msgid="5966994759929723339">"Uključeno"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nedostupno"</item>
+ <item msgid="2478289035899842865">"Isključeno"</item>
+ <item msgid="5137565285664080143">"Uključeno"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 62faafbf04bf..c7fec66fe9ae 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Калі вы ўведзяце няправільны PIN-код яшчэ раз, ваш працоўны профіль і звязаныя з ім даныя будуць выдалены."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Калі вы ўведзяце няправільны пароль яшчэ раз, ваш працоўны профіль і звязаныя з ім даныя будуць выдалены."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Дакраніцеся да сканера адбіткаў пальцаў"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Значок адбіткаў пальцаў"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Твар не распазнаны. Скарыстайце адбітак пальца."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Экран блакіроўкі дзейнасці"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыць"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яркасць"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Інверсія колераў"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Карэкцыя колераў"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Памер шрыфту"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Кіраваць карыстальнікамі"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Гатова"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Закрыць"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"запіс экрана"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без назвы"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Рэжым чакання"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Памер шрыфту"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Паменшыць"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Павялічыць"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Акно павелічэння"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Налады акна павелічэння"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Павялічыць маштаб"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Дададзены # элемент кіравання.}one{Дададзена # элемента кіравання.}few{Дададзена # элементы кіравання.}many{Дададзена # элементаў кіравання.}other{Дададзена # элемента кіравання.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Выдалена"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Дадаць праграму \"<xliff:g id="APPNAME">%s</xliff:g>\"?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Калі вы дадасце праграму \"<xliff:g id="APPNAME">%s</xliff:g>\", яна зможа дадаваць на гэту панэль налады і змесціва. Для некаторых праграм вы зможаце выбраць, якія налады будуць тут паказвацца."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Выдаліць налады для <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Дададзена ў абранае"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Дададзена ў абранае, пазіцыя <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Выдалена з абранага"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Іншае"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Дадаць у элементы кіравання прыладай"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Дадаць"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Выдаліць"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Прапанавана праграмай \"<xliff:g id="APP">%s</xliff:g>\""</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Прылада блакіравана"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Паказваць прылады і кіраваць імі з экрана блакіроўкі?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Вы можаце дадаць на экран блакіроўкі элементы кіравання знешнімі прыладамі.\n\nДзякуючы праграме на вашай прыладзе вы можаце кіраваць некаторымі прыладамі без разблакіроўкі тэлефона ці планшэта.\n\nУнесці змяненні можна ў любы час у Наладах."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Кіраваць прыладамі з экрана блакіроўкі?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Вы можаце кіраваць некаторымі прыладамі без разблакіроўкі тэлефона ці планшэта.\n\nПраграма на вашай прыладзе вызначае, якімі прыладамі можна кіраваць такім спосабам."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Не, дзякуй"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Так"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-код складаецца з літар або знакаў"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Дадаць элементы кіравання"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Змяніць элементы кіравання"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Дадаць праграму"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Выдаліць праграму"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Дадайце прылады вываду"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Выбрана 1 прылада"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Не ўдалося запусціць трансляцыю"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не ўдалося захаваць. Паўтарыце спробу."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не ўдалося захаваць."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Скарыстайце не менш як 4 сімвалы"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Скарыстайце менш за 16 сімвалаў"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Даступная хаця б адна прылада."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Дакраніцеся і ўтрымлівайце ярлык"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Скасаваць"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Пераключыцца на іншы экран"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Раскрыйце тэлефон"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Пераключыцца на іншы экран?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Каб рабіць фота з больш высокай раздзяляльнасцю, выкарыстоўвайце заднюю камеру"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Каб зрабіць фота з больш высокай раздзяляльнасцю, павярніце тэлефон"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Складная прылада ў раскладзеным выглядзе"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Перавернутая складная прылада"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Засталося зараду: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Пераключыцца на працоўны профіль"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрыць"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Налады экрана блакіроўкі"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Сетка Wi-Fi недаступная"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера заблакіравана"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера і мікрафон заблакіраваны"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрафон заблакіраваны"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Прыярытэтны рэжым уключаны"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/tiles_states_strings.xml b/packages/SystemUI/res/values-be/tiles_states_strings.xml
index 4050129df5c4..e71c29bd15de 100644
--- a/packages/SystemUI/res/values-be/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-be/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Выключана"</item>
<item msgid="5966994759929723339">"Уключана"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Недаступна"</item>
+ <item msgid="2478289035899842865">"Выключана"</item>
+ <item msgid="5137565285664080143">"Уключана"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index ad34919c17d1..9e55fa879829 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ако въведете неправилен ПИН код при следващия опит, служебният ви потребителски профил и данните в него ще бъдат изтрити."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ако въведете неправилна парола при следващия опит, служебният ви потребителски профил и данните в него ще бъдат изтрити."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Докоснете сензора за отпечатъци"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Икона за отпечатък"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Лицето не е разпознато. Използвайте отпечатък."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Заключен екран на служебния профил"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Затваряне"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яркост"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Цветове: инверт."</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекция на цветове"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Размер на шрифта"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Управление на потребителите"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Готово"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Затваряне"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"записване на екрана"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Няма заглавие"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Режим на готовност"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Размер на шрифта"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Намаляване на размера"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Увеличаване на размера"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за увеличение"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроли за прозореца за увеличение"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Увеличаване на мащаба"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Добавена е # контрола.}other{Добавени са # контроли.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Премахнато"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Да се добави ли <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Когато добавите <xliff:g id="APPNAME">%s</xliff:g>, приложението може да добави контроли и съдържание към този панел. Някои приложения ви дават възможност да избирате кои контроли да се показват тук."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Да се премахнат ли контролите за <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Означено като любимо"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Означено като любимо – позиция <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Не е означено като любимо"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Друго"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Добавяне към контролите за устройството"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Добавяне"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Премахване"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Предложено от <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"У-вото е заключено"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Да се показват ли устройствата на заключения екран и да се контролират ли оттам?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Можете да добавите към заключения екран контроли за външните си устройства.\n\nПриложението на устройството ви може да ви дава възможност да управлявате някои устройства, без да отключвате телефона или таблета си.\n\nПо всяко време можете да правите промени в „Настройки“."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Да се контролират ли устройствата от заключения екран?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Имате възможност да контролирате някои устройства, без да отключвате телефона или таблета си.\n\nПриложението на устройството ви определя кои устройства могат да бъдат контролирани по този начин."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Не, благодаря"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Да"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ПИН кодът съдържа букви или символи"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Добавяне на контроли"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Редактиране на контролите"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Добавяне на приложение"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Премахване на приложението"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Добавяне на изходящи устройства"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 избрано устройство"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Предаването не е възможно"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не може да се запази. Опитайте отново."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не може да се запази."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Използвайте поне 4 знака"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Използвайте по-малко от 16 знака"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Налице е поне едно устройство."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Докоснете и задръжте прекия път"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Отказ"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Превключване на екраните сега"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Отворете телефона"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Да се превключи ли екранът?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"За по-висока разделителна способност използвайте задната камера"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"За по-висока разделителна способност обърнете телефона"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Разгъване на сгъваемо устройство"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Обръщане на сгъваемо устройство"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Оставаща батерия: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Превключване към служебния потребителски профил"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Затваряне"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Настройки за заключения екран"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi не е налице"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Достъпът до камерата е блокиран"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Достъпът до камерата и микрофона е блокиран"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Достъпът до микрофона е блокиран"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетният режим е включен"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/tiles_states_strings.xml b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
index 011c62490606..24b41d23e900 100644
--- a/packages/SystemUI/res/values-bg/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Изкл."</item>
<item msgid="5966994759929723339">"Вкл."</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Не е налице"</item>
+ <item msgid="2478289035899842865">"Изключено"</item>
+ <item msgid="5137565285664080143">"Включено"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 319684206c6f..abc47ae944cc 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"আপনি পরের বারও ভুল পিন দিলে আপনার অফিস প্রোফাইল এবং তার ডেটা মুছে দেওয়া হবে।"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"আপনি পরের বারও ভুল পাসওয়ার্ড দিলে আপনার অফিস প্রোফাইল এবং তার ডেটা মুছে দেওয়া হবে।"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"আঙ্গুলের ছাপের সেন্সর স্পর্শ করুন"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"আঙ্গুলের ছাপের আইকন"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"মুখ শনাক্ত করতে পারছি না। পরিবর্তে আঙ্গুলের ছাপ ব্যবহার করুন।"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"কর্মস্থলের স্ক্রিন লক"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ করুন"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"উজ্জ্বলতা"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"কালার ইনভার্সন"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"রঙ সংশোধন"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ফন্ট সাইজ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ব্যবহারকারীদের ম্যানেজ করুন"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"সম্পন্ন হয়েছে"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"বন্ধ করুন"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"স্ক্রিন রেকর্ডিং"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"কোনও শীর্ষক নেই"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"স্ট্যান্ডবাই"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ফন্ট সাইজ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"আরও ছোট করুন"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"আরও বড় করুন"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"উইন্ডো বড় করে দেখা"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"উইন্ডো কন্ট্রোল বড় করে দেখা"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"বড় করুন"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{#টি কন্ট্রোল যোগ করা হয়েছে।}one{#টি কন্ট্রোল যোগ করা হয়েছে।}other{#টি কন্ট্রোল যোগ করা হয়েছে।}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"সরানো হয়েছে"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> যোগ করবেন?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"আপনি <xliff:g id="APPNAME">%s</xliff:g> যোগ করলে, এই প্যানেলে এটি কন্ট্রোল ও কন্টেন্ট যোগ করতে পারবে। কিছু অ্যাপের ক্ষেত্রে, এখানে কোন কোন কন্ট্রোল দেখা যাবে আপনি তা নিয়ন্ত্রণ করতে পারবেন।"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g>-এর জন্য নিয়ন্ত্রণ সরিয়ে দেবেন?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"পছন্দসই হিসেবে চিহ্নিত করেছেন"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"পছন্দসই হিসেবে চিহ্নিত করেছেন, অবস্থান <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"পছন্দসই থেকে সরিয়ে দিয়েছেন"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"অন্য"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ডিভাইস কন্ট্রোলে যোগ করুন"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"যোগ করুন"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"সরিয়ে দিন"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> সাজেস্ট করেছে"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"ডিভাইস লক করা আছে"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"লক স্ক্রিন থেকে ডিভাইস দেখতে এবং নিয়ন্ত্রণ করতে চান?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"লক স্ক্রিনে আপনার বাইরের ডিভাইসের জন্য কন্ট্রোল যোগ করা যাবে।\n\nআপনার ফোন বা ট্যাবলেট আনলক না করেই আপনার ডিভাইস অ্যাপ হয়ত কিছু ডিভাইস নিয়ন্ত্রণ করার সুবিধা দেবে\n\nসেটিংস থেকে যেকোনও সময়ে আপনি পরিবর্তন করতে পারবেন।"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"লক স্ক্রিন থেকে ডিভাইস নিয়ন্ত্রণ করতে চান?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"আপনি ফোন বা ট্যাবলেট আনলক না করেই কিছু ডিভাইস নিয়ন্ত্রণ করতে পারবেন।\n\nএইভাবে কোন ডিভাইস নিয়ন্ত্রণ করা হবে সেটি আপনার ডিভাইস অ্যাপ ঠিক করে।"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"না থাক"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"হ্যাঁ"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"পিন-এ অক্ষর বা চিহ্ন রয়েছে"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"কন্ট্রোল যোগ করুন"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"কন্ট্রোল এডিট করুন"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"অ্যাপ যোগ করুন"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"অ্যাপটি সরিয়ে দিন"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"আউটপুট যোগ করুন"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"গ্রুপ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"১টি ডিভাইস বেছে নেওয়া হয়েছে"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• অন্তত একটি ডিভাইস উপলভ্য"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"শর্টকাট টাচ করে ধরে রাখুন"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"বাতিল করুন"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"এখন স্ক্রিন পাল্টান"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ফোন আনফোল্ড করুন"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"স্ক্রিন পাল্টাবেন?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"আরও বেশি রেজোলিউশনের জন্য, রিয়ার ক্যামেরা ব্যবহার করুন"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"আরও বেশি রেজোলিউশনের জন্য, ফোন ফ্লিপ করুন"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ফোল্ড করা যায় এমন ডিভাইস খোলা হচ্ছে"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ফোল্ড করা যায় এমন ডিভাইস উল্টানো হচ্ছে"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ব্যাটারির চার্জ বাকি আছে"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"অফিস প্রোফাইলে পাল্টে নিন"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"বন্ধ করুন"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"লক স্ক্রিন সেটিংস"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ওয়াই-ফাই উপলভ্য নয়"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ক্যামেরার অ্যাক্সেস ব্লক করা আছে"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ক্যামেরা এবং মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\'প্রায়োরিটি\' মোড চালু করা আছে"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/tiles_states_strings.xml b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
index 00ce04e42e13..59061c223580 100644
--- a/packages/SystemUI/res/values-bn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"বন্ধ আছে"</item>
<item msgid="5966994759929723339">"চালু আছে"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"উপলভ্য নেই"</item>
+ <item msgid="2478289035899842865">"বন্ধ আছে"</item>
+ <item msgid="5137565285664080143">"চালু আছে"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 8134ec9944b1..db180f3a77d7 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ako u sljedećem pokušaju unesete neispravan PIN, vaš radni profil i njegovi podaci će se izbrisati."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ako u sljedećem pokušaju unesete neispravnu lozinku, vaš radni profil i njegovi podaci će se izbrisati."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dodirnite senzor za otisak prsta"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona za otisak prsta"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nije moguće prepoznati lice. Koristite otisak prsta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obavještenja sa sjenčenjem."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Brze postavke."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brze postavke i lokacija za obavještenja."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaključan ekran."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan ekran radnog profila"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvori"</string>
@@ -778,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"snimanje ekrana"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje mirovanja"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Veličina fonta"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Smanjivanje"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Povećavanje"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za uvećavanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za uvećavanje"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Uvećavanje"</string>
@@ -810,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Dodana je # kontrola.}one{Dodana je # kontrola.}few{Dodane su # kontrole.}other{Dodano je # kontrola.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Uklonjeno"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Dodati aplikaciju <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Kada dodate aplikaciju <xliff:g id="APPNAME">%s</xliff:g>, ona može dodavati kontrole i sadržaj na ovu ploču. U nekim aplikacijama možete odabrati koje kontrole se prikazuju ovdje."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Ukloniti kontrole za aplikaciju <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano u omiljeno"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano u omiljeno, pozicija <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Uklonjeno iz omiljenog"</string>
@@ -828,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Dodajte u kontrole uređaja"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Uklanjanje"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Predlaže <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Uređaj je zaključan"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Prikazati uređaje i kontrolirati njima sa zaključanog ekrana?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Na zaključani ekran možete dodati kontrole za eksterne uređaje.\n\nAplikacija vašeg uređaja vam može omogućiti da kontrolirate određene uređaje bez otključavanja telefona ili tableta.\n\nPromjene možete izvršiti bilo kada u Postavkama."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Kontrolirati uređaje sa zaključanog ekrana?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Neke uređaje možete kontrolirati bez otključavanja telefona ili tableta.\n\nAplikacija vašeg uređaja određuje koji uređaji se mogu kontrolirati na ovaj način."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, hvala"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Da"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN sadrži slova ili simbole"</string>
@@ -881,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrole"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Uredi kontrole"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikaciju"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Ukloni aplikaciju"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajte izlaze"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Odabran je 1 uređaj"</string>
@@ -1029,11 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Dostupan je najmanje jedan uređaj"</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>
- <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Promijenite zaslon odmah"</string>
- <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Otklopite telefon"</string>
- <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Želite li promijeniti zaslon?"</string>
- <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Za višu razlučivost upotrijebite stražnju kameru"</string>
- <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za višu razlučivost okrenite telefon"</string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Promijenite ekran sada"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Rasklopite telefon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Promijeniti ekran?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Za višu rezoluciju koristite zadnju kameru"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za višu rezoluciju obrnite telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Sklopivi uređaj se rasklapa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Sklopivi uređaj se obrće"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Preostalo baterije: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1045,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Pređite na radni profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Postavke zaključavanja ekrana"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi mreža nije dostupna"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon su blokirani"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Način rada Prioriteti je uključen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index ca8a4c366094..04ea9c02269c 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Si tornes a introduir un PIN incorrecte, se suprimirà el perfil de treball i les dades que contingui."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Si tornes a introduir una contrasenya incorrecta, se suprimirà el perfil de treball i les dades que contingui."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca el sensor d\'empremtes digitals"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icona d\'empremta digital"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No podem detectar la cara. Usa l\'empremta digital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Àrea de notificacions"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuració ràpida"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuració ràpida i àrea de notificacions."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueig"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueig per a la feina"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Tanca"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillantor"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversió de colors"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correcció de color"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Cos de font"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gestiona els usuaris"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Fet"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Tanca"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Comença ara"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"No hi ha cap notificació"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"No hi ha cap notificació nova"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloq. per veure notificacions antigues"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueja per veure notif. anteriors"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Els teus pares gestionen aquest dispositiu"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"La teva organització és propietària del dispositiu i és possible que supervisi el trànsit de xarxa"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> és propietària d\'aquest dispositiu i és possible que supervisi el trànsit de xarxa"</string>
@@ -675,7 +674,7 @@
<string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"suprimir el mosaic"</string>
<string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"afegir un mosaic al final"</string>
<string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mou el mosaic"</string>
- <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Afegeix un mosaic"</string>
+ <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Afegeix una icona"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mou a la posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Afegeix a la posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"gravació de pantalla"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sense títol"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Cos de font"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Redueix"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Amplia"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Finestra d\'ampliació"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Finestra de controls d\'ampliació"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Amplia"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{S\'ha afegit # control.}many{S\'han afegit # controls.}other{S\'han afegit # controls.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Suprimit"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Vols afegir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"En afegir <xliff:g id="APPNAME">%s</xliff:g>, podrà afegir controls i contingut en aquest tauler. En algunes aplicacions, pots triar quins controls es mostren aquí."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vols suprimir els controls per a <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Afegit als preferits"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Afegit als preferits, posició <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Suprimit dels preferits"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Altres"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Afegeix als controls de dispositius"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Afegeix"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Suprimeix"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Suggerit per <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Dispositiu bloquejat"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vols mostrar i controlar dispositius a la pantalla de bloqueig?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Pots afegir controls dels teus dispositius externs a la pantalla de bloqueig.\n\nL\'aplicació del dispositiu et pot permetre controlar alguns dispositius sense desbloquejar el telèfon o la tauleta.\n\nPots fer canvis en qualsevol moment a Configuració."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vols controlar dispositius des de la pantalla de bloqueig?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Pots controlar alguns dispositius sense desbloquejar el telèfon o la tauleta.\n\nL\'aplicació del dispositiu determina quins dispositius es poden controlar d\'aquesta manera."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, gràcies"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sí"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"El PIN conté lletres o símbols"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Afegeix controls"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edita els controls"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Afegeix una aplicació"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Suprimeix l\'aplicació"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Afegeix sortides"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositiu seleccionat"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"No es pot emetre"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilitza 4 caràcters com a mínim"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilitza menys de 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Almenys un dispositiu està disponible."</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Canvia de pantalla ara"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Desplega el telèfon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vols canviar de pantalla?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Per a una resolució més alta, utilitza la càmera posterior"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Per a una resolució més alta, gira el telèfon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositiu plegable desplegant-se"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositiu plegable girant"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de bateria"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Canvia al perfil de treball"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Tanca"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Configuració pantalla de bloqueig"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"No hi ha cap Wi‑Fi disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La càmera està bloquejada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La càmera i el micròfon estan bloquejats"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micròfon està bloquejat"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El mode Prioritat està activat"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/tiles_states_strings.xml b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
index 067b970226d8..e99926c57324 100644
--- a/packages/SystemUI/res/values-ca/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Desactivat"</item>
<item msgid="5966994759929723339">"Activat"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"No disponible"</item>
+ <item msgid="2478289035899842865">"Desactivat"</item>
+ <item msgid="5137565285664080143">"Activat"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 0e6643ef6a52..1cb36996cab4 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Pokud při příštím pokusu zadáte nesprávný PIN, váš pracovní profil a přidružená data budou smazána."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Pokud při příštím pokusu zadáte nesprávné heslo, váš pracovní profil a přidružená data budou smazána."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotkněte se snímače otisků prstů"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona otisku prstu"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Obličej se nepodařilo rozpoznat. Použijte místo něj otisk prstu."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel oznámení."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rychlé nastavení."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Rychlé nastavení a panel oznámení"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Obrazovka uzamčení"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Obrazovka uzamčení pracovního profilu"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zavřít"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Jas"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Převrácení barev"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekce barev"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Velikost písma"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Správa uživatelů"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Hotovo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zavřít"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"nahrávání obrazovky"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Pohotovostní režim"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Velikost písma"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Zmenšit"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Zvětšit"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Zvětšovací okno"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ovládací prvky zvětšovacího okna"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Přiblížit"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Byl přidán # ovládací prvek.}few{Byly přidány # ovládací prvky.}many{Bylo přidáno # ovládacího prvku.}other{Bylo přidáno # ovládacích prvků.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Odstraněno"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Přidat aplikaci <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Když přidáte aplikaci <xliff:g id="APPNAME">%s</xliff:g>, může do tohoto panelu přidat ovládací prvky a obsah. V některých aplikacích si můžete vybrat, které ovládací prvky se zde zobrazí."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Odstranit ovládací prvky aplikace <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Přidáno do oblíbených"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Přidáno do oblíbených na pozici <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odebráno z oblíbených"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Jiné"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Přidání ovládání zařízení"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Přidat"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Odstranit"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Návrh z aplikace <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Zařízení uzamčeno"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Zobrazovat a ovládat zařízení z obrazovky uzamčení?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Na obrazovku uzamčení můžete přidat ovládací prvky pro svá externí zařízení.\n\nAplikace zařízení vám může umožnit ovládat některá zařízení bez odemykání telefonu nebo tabletu.\n\nZměny můžete kdykoli provést v Nastavení."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Ovládat zařízení z obrazovky uzamčení?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Některá zařízení můžete ovládat bez odemykání telefonu nebo tabletu.\n\nAplikace zařízení určuje, která zařízení lze tímto způsobem ovládat."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, díky"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ano"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Kód PIN obsahuje písmena nebo symboly"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Přidat ovládací prvky"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Upravit ovládací prvky"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Přidat aplikaci"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Odstranit aplikaci"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Přidání výstupů"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Je vybráno 1 zařízení"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Je k dispozici alespoň jedno zařízení"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Přepnout obrazovky"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Rozevřete telefon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Přepnout obrazovky?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Pomocí zadního fotoaparátu dosáhnete vyššího rozlišení"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Otočte telefon, abyste dosáhli vyššího rozlišení"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rozkládání rozkládacího zařízení"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Otáčení rozkládacího zařízení"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g> baterie"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Přepnout na pracovní profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zavřít"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Nastavení obrazovky uzamčení"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Síť Wi-Fi není dostupná"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokována"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera a mikrofon jsou blokovány"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokován"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Režim priority je zapnutý"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/tiles_states_strings.xml b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
index df3d403d14dc..6359f94112bb 100644
--- a/packages/SystemUI/res/values-cs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Vypnuto"</item>
<item msgid="5966994759929723339">"Zapnuto"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nedostupné"</item>
+ <item msgid="2478289035899842865">"Vypnuto"</item>
+ <item msgid="5137565285664080143">"Zapnuto"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 0fc389736447..9050ea26395d 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Hvis du angiver en forkert pinkode i næste forsøg, slettes din arbejdsprofil og de tilhørende data."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Hvis du angiver en forkert adgangskode i næste forsøg, slettes din arbejdsprofil og de tilhørende data."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sæt fingeren på fingeraftrykssensoren"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikon for fingeraftryk"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansigtet kan ikke genkendes. Brug fingeraftryk i stedet."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notifikationspanel."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kvikmenu."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kvikmenu og notifikationspanel."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låseskærm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låseskærm til arbejde"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Luk"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Lysstyrke"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ombytning af farver"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Farvekorrigering"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Skriftstørrelse"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Administrer brugere"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Udfør"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Luk"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"skærmoptagelse"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Skriftstørrelse"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Formindsk"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Forstør"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vindue med forstørrelse"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vindue med forstørrelsesstyring"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom ind"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# styringselement er tilføjet.}one{# styringselement er tilføjet.}other{# styringselementer er tilføjet.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Fjernet"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Vil du tilføje <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Når du tilføjer <xliff:g id="APPNAME">%s</xliff:g>, kan den føje styringselementer og indhold til dette panel. I nogle apps kan du vælge, hvilke styringselementer der vises her."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vil du fjerne styringselementerne for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Angivet som favorit"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Angivet som favorit. Position <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjernet fra favoritter"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Andre"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Føj til enhedsstyring"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Tilføj"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Fjern"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Foreslået af <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Enheden er låst"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vil du se og styre enheder via låseskærmen?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Du kan tilføje styringselementer til dine eksterne enheder på låseskærmen.\n\nMed din enhedsapp kan du muligvis styre visse enheder uden at låse op for din telefon eller tablet.\n\nDu kan til enhver tid foretage ændringer i Indstillinger."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vil du styre enheder via låseskærmen?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Du kan styre visse enheder uden at låse op for din telefon eller tablet.\n\nDin enhedsapp bestemmer, hvilke enheder der kan styres på denne måde."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nej tak"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Pinkoden indeholder bogstaver eller symboler"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Tilføj styring"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Rediger styring"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tilføj app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Fjern app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tilføj medieudgange"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Der er valgt 1 enhed"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Der kan ikke udsendes en fællesbesked"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Angiv mindst 4 tegn"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Angiv højst 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Mindst én enhed er tilgængelig"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Skift skærm nu"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Fold telefonen ud"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vil du skifte skærm?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Brug kameraet på bagsiden for at få højere opløsning"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Vend telefonen for at få højere opløsning"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldbar enhed foldes ud"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldbar enhed vendes om"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batteri tilbage"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Skift til arbejdsprofil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Luk"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Indstillinger for låseskærm"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ikke tilgængeligt"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameraet er blokeret"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Der er blokeret for kameraet og mikrofonen"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen er blokeret"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetstilstand er aktiveret"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/tiles_states_strings.xml b/packages/SystemUI/res/values-da/tiles_states_strings.xml
index 7e2f87de778e..1daed4cd6864 100644
--- a/packages/SystemUI/res/values-da/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-da/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Fra"</item>
<item msgid="5966994759929723339">"Til"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ikke tilgængelig"</item>
+ <item msgid="2478289035899842865">"Fra"</item>
+ <item msgid="5137565285664080143">"Til"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index d6568e7b1b8c..498a1e67aeab 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Wenn du beim nächsten Versuch eine falsche PIN eingibst, werden dein Arbeitsprofil und die zugehörigen Daten gelöscht."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Wenn du beim nächsten Versuch ein falsches Passwort eingibst, werden dein Arbeitsprofil und die zugehörigen Daten gelöscht."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Berühre den Fingerabdrucksensor"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingerabdruck-Symbol"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Gesicht wurde nicht erkannt. Verwende stattdessen den Fingerabdruck."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Benachrichtigungsleiste"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Schnelleinstellungen"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Schnelleinstellungen und Benachrichtigungsleiste."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Sperrbildschirm"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Sperrbildschirm für Arbeitsprofil"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Schließen"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Helligkeit"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Farbumkehr"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Farbkorrektur"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Schriftgröße"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Nutzer verwalten"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Fertig"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Schließen"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"Bildschirmaufzeichnung"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Kein Titel"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Schriftgröße"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Verkleinern"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Vergrößern"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrößerungsfenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Einstellungen für Vergrößerungsfenster"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Heranzoomen"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# Steuerelement hinzugefügt.}other{# Steuerelemente hinzugefügt.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Entfernt"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> hinzufügen?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Wenn du <xliff:g id="APPNAME">%s</xliff:g> hinzufügst, kann diese App Einstellungen und Inhalte zu diesem Bereich hinzufügen. In einigen Apps kannst du festlegen, welche Einstellungen hier angezeigt werden sollen."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Einstellungen für <xliff:g id="APPNAME">%s</xliff:g> entfernen?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Zu Favoriten hinzugefügt"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Zu Favoriten hinzugefügt, Position <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Aus Favoriten entfernt"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Andere"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Zur Gerätesteuerung hinzufügen"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Hinzufügen"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Entfernen"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Vorgeschlagen von <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Gerät gesperrt"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Geräte auf Sperrbildschirm anzeigen und steuern?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Du kannst dem Sperrbildschirm Steuerelemente für deine externen Geräte hinzufügen.\n\nDie App deines Geräts ermöglicht dir eventuell, einige Geräte zu steuern, ohne dein Smartphone oder Tablet zu entsperren.\n\nDu kannst jederzeit Änderungen in den Einstellungen vornehmen."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Geräte über den Sperrbildschirm steuern?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Du kannst einige Geräte steuern, ohne das Smartphone oder Tablet zu entsperren.\n\nDie App deines Geräts bestimmt, welche Geräte auf diese Weise gesteuert werden können."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nein danke"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Die PIN enthält Buchstaben oder Symbole"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Steuerelemente hinzufügen"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Steuerelemente bearbeiten"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"App hinzufügen"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"App entfernen"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ausgabegeräte hinzufügen"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Ein Gerät ausgewählt"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Mindestens ein Gerät ist verfügbar"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Bildschirm jetzt wechseln"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Smartphone auffalten"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Bildschirm wechseln?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Mit der Rückkamera lassen sich Fotos mit höherer Auflösung aufnehmen"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Smartphone umdrehen, um Fotos mit höherer Auflösung aufzunehmen"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Faltbares Gerät wird geöffnet"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Faltbares Gerät wird umgeklappt"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akku bei <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Zum Arbeitsprofil wechseln"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Schließen"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Sperrbildschirm-Einstellungen"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Kein WLAN verfügbar"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera blockiert"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera und Mikrofon blockiert"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon blockiert"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritätsmodus an"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/tiles_states_strings.xml b/packages/SystemUI/res/values-de/tiles_states_strings.xml
index bd73a0583c53..9a087472bd03 100644
--- a/packages/SystemUI/res/values-de/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-de/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Aus"</item>
<item msgid="5966994759929723339">"An"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nicht verfügbar"</item>
+ <item msgid="2478289035899842865">"Aus"</item>
+ <item msgid="5137565285664080143">"An"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 7b413edd78db..af0f7283f70c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Εάν εισαγάγετε εσφαλμένο PIN στην επόμενη προσπάθεια, το προφίλ εργασίας σας και τα δεδομένα του θα διαγραφούν."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Εάν εισαγάγετε εσφαλμένο κωδικό πρόσβασης στην επόμενη προσπάθεια, το προφίλ εργασίας σας και τα δεδομένα του θα διαγραφούν."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Αγγίξτε τον αισθητήρα δακτυλικού αποτυπώματος"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Εικονίδιο δακτυλικών αποτυπωμάτων"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Το πρόσωπο δεν αναγνωρίζεται. Χρησιμ. δακτ. αποτ."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Οθόνη κλειδωμένης εργασίας"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Κλείσιμο"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Φωτεινότητα"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Αντιστροφή χρωμάτων"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Διόρθωση χρωμάτων"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Μέγεθος γραμματοσειράς"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Διαχείριση χρηστών"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Τέλος"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Κλείσιμο"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"εγγραφή οθόνης"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Χωρίς τίτλο"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Κατάσταση αναμονής"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Μέγεθος γραμματοσειράς"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Να μικρύνουν"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Να μεγαλώσουν"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Παράθυρο μεγέθυνσης"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Στοιχεία ελέγχου παραθύρου μεγέθυνσης"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Μεγέθυνση"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Προστέθηκε # στοιχείο ελέγχου.}other{Προστέθηκαν # στοιχεία ελέγχου.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Καταργήθηκε"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Προσθήκη <xliff:g id="APPNAME">%s</xliff:g>;"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Όταν προσθέσετε την εφαρμογή <xliff:g id="APPNAME">%s</xliff:g>, μπορεί να προσθέσει στοιχεία ελέγχου και περιεχόμενο σε αυτό το πλαίσιο. Σε ορισμένες εφαρμογές, μπορείτε να επιλέξετε ποια στοιχεία ελέγχου θα εμφανίζονται εδώ."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Κατάργηση στοιχείων ελέγχου για την εφαρμογή <xliff:g id="APPNAME">%s</xliff:g>;"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Προστέθηκε στα αγαπημένα"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Προστέθηκε στα αγαπημένα, στη θέση <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Αφαιρέθηκε από τα αγαπημένα"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Άλλο"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Προσθήκη στα στοιχεία ελέγχου συσκευής"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Προσθήκη"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Κατάργηση"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Προτείνεται από <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Η συσκευή κλειδώθηκε"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Εμφάνιση και έλεγχος συσκευών από την οθόνη κλειδώματος;"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Μπορείτε να προσθέσετε στοιχεία ελέγχου για τις εξωτερικές συσκευές σας στην οθόνη κλειδώματος.\n\nΗ εφαρμογή της συσκευής σας μπορεί να σας παρέχει τη δυνατότητα ελέγχου ορισμένων συσκευών χωρίς να ξεκλειδώσετε το τηλέφωνο ή το tablet.\n\nΜπορείτε να κάνετε αλλαγές στις Ρυθμίσεις ανά πάσα στιγμή."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Έλεγχος συσκευών από την οθόνη κλειδώματος;"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Μπορείτε να ελέγχετε ορισμένες συσκευές χωρίς να ξεκλειδώσετε το τηλέφωνο ή το tablet σας.\n\nΗ εφαρμογή της συσκευής σας καθορίζει ποιες συσκευές μπορούν να ελέγχονται με αυτόν τον τρόπο."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Όχι, ευχαριστώ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ναι"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Το PIN περιέχει γράμματα ή σύμβολα"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Προσθήκη στοιχείων ελέγχου"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Επεξεργασία στοιχείων ελέγχου"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Προσθήκη εφαρμογής"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Κατάργηση εφαρμογής"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Προσθήκη εξόδων"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Ομάδα"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Επιλέχτηκε 1 συσκευή"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Δεν είναι δυνατή η μετάδοση"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Δεν είναι δυνατή η αποθήκευση. Δοκιμάστε ξανά."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Δεν είναι δυνατή η αποθήκευση."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Χρησιμοποιήστε τουλάχιστον 4 χαρακτήρες"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Χρησιμοποιήστε λιγότερους από 16 χαρακτήρες"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Είναι διαθέσιμη τουλάχιστον μία συσκευή"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Παρατεταμένο άγγιγμα συντόμευσης"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Ακύρωση"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Εναλλαγή οθονών τώρα"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Ξεδιπλώστε το τηλέφωνο"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Αλλαγή οθονών;"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Για υψηλότερη ανάλυση, χρησιμοποιήστε την πίσω κάμερα"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Για υψηλότερη ανάλυση, αναστρέψτε το τηλέφωνο"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Αναδιπλούμενη συσκευή που ξεδιπλώνει"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Αναδιπλούμενη συσκευή που διπλώνει"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Απομένει το <xliff:g id="PERCENTAGE">%s</xliff:g> της μπαταρίας"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Εναλλαγή σε προφίλ εργασίας"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Κλείσιμο"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Ρυθμίσεις κλειδώματος οθόνης"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Δεν υπάρχει διαθέσιμο δίκτυο Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Η κάμερα έχει αποκλειστεί"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Η κάμερα και το μικρόφωνο έχουν αποκλειστεί"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Το μικρόφωνο έχει αποκλειστεί"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Η λειτουργία προτεραιότητας είναι ενεργοποιημένη"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/tiles_states_strings.xml b/packages/SystemUI/res/values-el/tiles_states_strings.xml
index 5c7c7380943a..4d94515ac130 100644
--- a/packages/SystemUI/res/values-el/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-el/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Ανενεργό"</item>
<item msgid="5966994759929723339">"Ενεργό"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Μη διαθέσιμο"</item>
+ <item msgid="2478289035899842865">"Ανενεργό"</item>
+ <item msgid="5137565285664080143">"Ενεργό"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 5b6c106115cc..a29bcb279520 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"If you enter an incorrect PIN on the next attempt, your work profile and its data will be deleted."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"If you enter an incorrect password on the next attempt, your work profile and its data will be deleted."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingerprint icon"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick Settings and notification shade."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
@@ -778,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"screen recording"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Font size"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Make smaller"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Make larger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
@@ -810,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control added.}other{# controls added.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Add <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"When you add <xliff:g id="APPNAME">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remove controls for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Favourited"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favourited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavourited"</string>
@@ -828,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Remove"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Show and control devices from the lock screen?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"You can add controls for your external devices to the lock screen.\n\nYour device app may allow you to control some devices without unlocking your phone or tablet.\n\nYou can make changes at any time in Settings."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Control devices from the lock screen?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, thanks"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yes"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
@@ -881,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Add app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Remove app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
@@ -1045,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera is blocked"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone is blocked"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 50134c831bee..64618d04090a 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"If you enter an incorrect PIN on the next attempt, your work profile and its data will be deleted."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"If you enter an incorrect password on the next attempt, your work profile and its data will be deleted."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingerprint icon"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognize face. Use fingerprint instead."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick settings and Notification shade."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
@@ -778,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"screen recording"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Font Size"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Make smaller"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Make larger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification Window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification Window Controls"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
@@ -810,7 +807,8 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control added.}other{# controls added.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Add <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"When you add <xliff:g id="APPNAME">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here."</string>
+ <string name="controls_panel_authorization" msgid="4665218066461350247">"<xliff:g id="APPNAME">%s</xliff:g>can choose which controls and content show here."</string>
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remove controls for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Favorited"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favorited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavorited"</string>
@@ -828,12 +826,13 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Remove"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Show and control devices from lock screen?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"You can add controls for your external devices to the lock screen.\n\nYour device app may allow you to control some devices without unlocking your phone or tablet.\n\nYou can make changes any time in Settings."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Control devices from lock screen?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way."</string>
+ <string name="controls_settings_trivial_controls_dialog_message" msgid="397178734990952575">"You can control some devices without unlocking your phone or tablet. Your device app determines which devices can be controlled in this way."</string>
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No thanks"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yes"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
@@ -881,6 +880,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Add app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Remove app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 device selected"</string>
@@ -1045,4 +1045,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera blocked"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone blocked"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 5b6c106115cc..a29bcb279520 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"If you enter an incorrect PIN on the next attempt, your work profile and its data will be deleted."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"If you enter an incorrect password on the next attempt, your work profile and its data will be deleted."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingerprint icon"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick Settings and notification shade."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
@@ -778,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"screen recording"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Font size"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Make smaller"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Make larger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
@@ -810,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control added.}other{# controls added.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Add <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"When you add <xliff:g id="APPNAME">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remove controls for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Favourited"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favourited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavourited"</string>
@@ -828,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Remove"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Show and control devices from the lock screen?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"You can add controls for your external devices to the lock screen.\n\nYour device app may allow you to control some devices without unlocking your phone or tablet.\n\nYou can make changes at any time in Settings."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Control devices from the lock screen?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, thanks"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yes"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
@@ -881,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Add app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Remove app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
@@ -1045,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera is blocked"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone is blocked"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 5b6c106115cc..a29bcb279520 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"If you enter an incorrect PIN on the next attempt, your work profile and its data will be deleted."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"If you enter an incorrect password on the next attempt, your work profile and its data will be deleted."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingerprint icon"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick Settings and notification shade."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
@@ -778,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"screen recording"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Font size"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Make smaller"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Make larger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
@@ -810,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control added.}other{# controls added.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Add <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"When you add <xliff:g id="APPNAME">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remove controls for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Favourited"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favourited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavourited"</string>
@@ -828,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Remove"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Show and control devices from the lock screen?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"You can add controls for your external devices to the lock screen.\n\nYour device app may allow you to control some devices without unlocking your phone or tablet.\n\nYou can make changes at any time in Settings."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Control devices from the lock screen?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, thanks"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yes"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
@@ -881,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Add app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Remove app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
@@ -1045,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera is blocked"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone is blocked"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index f8f77591c8bb..72c1a195079a 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎If you enter an incorrect PIN on the next attempt, your work profile and its data will be deleted.‎‏‎‎‏‎"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎If you enter an incorrect password on the next attempt, your work profile and its data will be deleted.‎‏‎‎‏‎"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎Touch the fingerprint sensor‎‏‎‎‏‎"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎Fingerprint icon‎‏‎‎‏‎"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‏‎‎‎Can’t recognize face. Use fingerprint instead.‎‏‎‎‏‎"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‎‏‏‎‏‏‎‏‎‏‎Notification shade.‎‏‎‎‏‎"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‎‏‏‎Quick settings.‎‏‎‎‏‎"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎Quick settings and Notification shade.‎‏‎‎‏‎"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎Lock screen.‎‏‎‎‏‎"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‏‏‏‎Work lock screen‎‏‎‎‏‎"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‏‎Close‎‏‎‎‏‎"</string>
@@ -778,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎screen recording‎‏‎‎‏‎"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎No title‎‏‎‎‏‎"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎Standby‎‏‎‎‏‎"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎Font Size‎‏‎‎‏‎"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‎Make smaller‎‏‎‎‏‎"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎Make larger‎‏‎‎‏‎"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‏‎‏‎Magnification Window‎‏‎‎‏‎"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎Magnification Window Controls‎‏‎‎‏‎"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎Zoom in‎‏‎‎‏‎"</string>
@@ -810,7 +807,8 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‏‏‎# control added.‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‏‏‎# controls added.‎‏‎‎‏‎}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‏‏‏‏‏‏‎Removed‎‏‎‎‏‎"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎Add ‎‏‎‎‏‏‎<xliff:g id="APPNAME">%s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‏‎‏‏‏‎When you add ‎‏‎‎‏‏‎<xliff:g id="APPNAME">%s</xliff:g>‎‏‎‎‏‏‏‎, it can add controls and content to this panel. In some apps, you can choose which controls show up here.‎‏‎‎‏‎"</string>
+ <string name="controls_panel_authorization" msgid="4665218066461350247">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="APPNAME">%s</xliff:g>‎‏‎‎‏‏‏‎can choose which controls and content show here.‎‏‎‎‏‎"</string>
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‎‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‏‎‎‎‎‏‎‎Remove controls for ‎‏‎‎‏‏‎<xliff:g id="APPNAME">%s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‎Favorited‎‏‎‎‏‎"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎Favorited, position ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎Unfavorited‎‏‎‎‏‎"</string>
@@ -828,12 +826,13 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎Other‎‏‎‎‏‎"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‏‏‎‏‎‎Add to device controls‎‏‎‎‏‎"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎Add‎‏‎‎‏‎"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎Remove‎‏‎‎‏‎"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎‎Suggested by ‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎Device locked‎‏‎‎‏‎"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‎‎‏‎‎Show and control devices from lock screen?‎‏‎‎‏‎"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‏‎You can add controls for your external devices to the lock screen.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Your device app may allow you to control some devices without unlocking your phone or tablet.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎You can make changes any time in Settings.‎‏‎‎‏‎"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎Control devices from lock screen?‎‏‎‎‏‎"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎You can control some devices without unlocking your phone or tablet.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Your device app determines which devices can be controlled in this way.‎‏‎‎‏‎"</string>
+ <string name="controls_settings_trivial_controls_dialog_message" msgid="397178734990952575">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‎You can control some devices without unlocking your phone or tablet. Your device app determines which devices can be controlled in this way.‎‏‎‎‏‎"</string>
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‎No thanks‎‏‎‎‏‎"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎Yes‎‏‎‎‏‎"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‎‎PIN contains letters or symbols‎‏‎‎‏‎"</string>
@@ -881,6 +880,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‎Add controls‎‏‎‎‏‎"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎‏‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‎‎Edit controls‎‏‎‎‏‎"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‎Add app‎‏‎‎‏‎"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎‎Remove app‎‏‎‎‏‎"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‎Add outputs‎‏‎‎‏‎"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‎Group‎‏‎‎‏‎"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎1 device selected‎‏‎‎‏‎"</string>
@@ -1045,4 +1045,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‎Switch to work profile‎‏‎‎‏‎"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎Close‎‏‎‎‏‎"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎Lock screen settings‎‏‎‎‏‎"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‎‎‎Wi-Fi not available‎‏‎‎‏‎"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎Camera blocked‎‏‎‎‏‎"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‎‎Camera and microphone blocked‎‏‎‎‏‎"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‎Microphone blocked‎‏‎‎‏‎"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎‎Priority mode on‎‏‎‎‏‎"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 4b49a20551f5..368b2a290dc0 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Si ingresas un PIN incorrecto en el próximo intento, se borrarán tu perfil de trabajo y sus datos."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Si ingresas una contraseña incorrecta en el próximo intento, se borrarán tu perfil de trabajo y sus datos."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca el sensor de huellas dactilares"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ícono de huella dactilar"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No se reconoce el rostro. Usa la huella dactilar."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pantalla de notificaciones"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuración rápida"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuración rápida y panel de notificaciones."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla bloqueada del perfil de trabajo"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Cerrar"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillo"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Invertir colores"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corregir colores"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamaño de la fuente"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Administrar usuarios"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Listo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Cerrar"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Comenzar ahora"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"No hay notificaciones"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"No hay notificaciones nuevas"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notif. anteriores"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notificaciones anteriores"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Tu padre o madre administra este dispositivo"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Tu organización es propietaria de este dispositivo y podría controlar el tráfico de red"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> es la organización propietaria de este dispositivo y podría controlar el tráfico de red"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"Grabación de pant."</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamaño de fuente"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Reducir tamaño"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar tamaño"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controles de ampliación de la ventana"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Acercar"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Se agregó # control.}many{Se agregaron # controles.}other{Se agregaron # controles.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Quitados"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"¿Quieres agregar <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Si agregas la app de <xliff:g id="APPNAME">%s</xliff:g>, se incluirán controles y contenido en este panel. Algunas apps te permiten elegir qué controles mostrar aquí."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"¿Quieres quitar los controles para <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Está en favoritos"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Está en favoritos en la posición <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"No está en favoritos"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Otros"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Agregar a controles de dispositivos"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Agregar"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Quitar"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Dispos. bloqueado"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"¿Quieres mostrar y controlar dispositivos desde la pantalla de bloqueo?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Puedes agregar controles para dispositivos externos a la pantalla de bloqueo.\n\nLa app de tu dispositivo podría permitirte controlar algunos dispositivos sin desbloquear el teléfono o la tablet.\n\nPuedes realizar cambios en cualquier momento en Configuración."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"¿Quieres controlar dispositivos desde la pantalla de bloqueo?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Puedes controlar algunos dispositivos sin desbloquear el teléfono o la tablet.\n\nLa app de tu dispositivo determina los que se pueden controlar de esa manera."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, gracias"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sí"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"El PIN contiene letras o símbolos"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Agregar controles"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Agregar app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Quitar app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Agregar salidas"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Se seleccionó 1 dispositivo"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Error al iniciar transmisión"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa al menos 4 caracteres"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa menos de 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Hay al menos un dispositivo disponible."</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Cambiar de pantalla ahora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Despliega el teléfono"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"¿Quieres cambiar de pantalla?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para obtener una resolución más alta, usa la cámara posterior."</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para obtener una resolución más alta, gira el teléfono"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable siendo desplegado"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo plegable siendo girado"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> de batería restante"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Config. de pantalla de bloqueo"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi no disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La cámara está bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La cámara y el micrófono están bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micrófono está bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El modo de prioridad está activado"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
index e15610096626..bb3983b0bb09 100644
--- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"No"</item>
<item msgid="5966994759929723339">"Sí"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"No disponible"</item>
+ <item msgid="2478289035899842865">"Desactivado"</item>
+ <item msgid="5137565285664080143">"Activado"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a180e2cf2f6d..86ef07fff1ee 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -51,8 +51,8 @@
<string name="usb_debugging_message" msgid="5794616114463921773">"La huella digital de tu clave RSA es:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
<string name="usb_debugging_always" msgid="4003121804294739548">"Permitir siempre desde este ordenador"</string>
<string name="usb_debugging_allow" msgid="1722643858015321328">"Permitir"</string>
- <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Depuración USB no permitida"</string>
- <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"El usuario con el que se ha iniciado sesión en este dispositivo no puede activar la depuración USB. Para utilizar esta función, inicia sesión con la cuenta de usuario principal."</string>
+ <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Depuración por USB no permitida"</string>
+ <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"El usuario con el que se ha iniciado sesión en este dispositivo no puede activar la depuración por USB. Para utilizar esta función, inicia sesión con la cuenta de usuario principal."</string>
<string name="hdmi_cec_set_menu_language_title" msgid="1259765420091503742">"¿Quieres cambiar el idioma del sistema a <xliff:g id="LANGUAGE">%1$s</xliff:g>?"</string>
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Otro dispositivo ha solicitado un cambio en el idioma del sistema"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Cambiar idioma"</string>
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Si vuelves a introducir un PIN incorrecto, tu perfil de trabajo y sus datos se eliminarán."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Si vuelves a introducir una contraseña incorrecta, tu perfil de trabajo y sus datos se eliminarán."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca el sensor de huellas digitales"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icono de huella digital"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No se reconoce la cara. Usa la huella digital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pantalla de notificaciones"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ajustes rápidos"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ajustes rápidos y pantalla de notificaciones."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueo para el perfil de trabajo"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Cerrar"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillo"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Invertir colores"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corrección de color"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamaño de fuente"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gestionar usuarios"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Hecho"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Cerrar"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Empezar ahora"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"No hay notificaciones"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"No hay notificaciones nuevas"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notif. anteriores"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notificaciones anteriores"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo lo gestionan tu padre o tu madre"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"El dispositivo pertenece a tu organización, que puede monitorizar su tráfico de red"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"El dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, que puede monitorizar su tráfico de red"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"grabación de pantalla"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamaño de fuente"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Reducir tamaño"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar tamaño"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ventana de controles de ampliación"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Ampliar"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control añadido.}many{# controles añadidos.}other{# controles añadidos.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Quitado"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"¿Añadir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Si añades <xliff:g id="APPNAME">%s</xliff:g>, podrá añadir controles y contenido a este panel. En algunas aplicaciones, puedes elegir qué controles aparecen aquí."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"¿Quitar los controles de <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Añadido a favoritos"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Añadido a favoritos (posición <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Quitado de favoritos"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Otros"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Añadir a control de dispositivos"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Añadir"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Quitar"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloqueado"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"¿Mostrar y controlar otros dispositivos en la pantalla de bloqueo?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Puedes añadir controles de tus dispositivos externos a la pantalla de bloqueo.\n\nPuede que la aplicación de tu dispositivo permita que controles algunos dispositivos sin desbloquear tu teléfono o tablet.\n\nPuedes hacer cambios en cualquier momento en Ajustes."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"¿Controlar dispositivos desde la pantalla de bloqueo?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Puedes controlar algunos dispositivos sin desbloquear tu teléfono o tablet.\n\nLa aplicación de tu dispositivo determina qué dispositivos se pueden controlar de esta forma."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, gracias"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sí"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"El PIN contiene letras o símbolos"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Añadir controles"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Añadir aplicación"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Quitar aplicación"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Añadir dispositivos de salida"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo seleccionado"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"No se puede emitir"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa 4 caracteres como mínimo"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa menos de 16 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>
@@ -963,7 +962,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
- <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string>
+ <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectado temporalmente"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión inestable"</string>
<string name="mobile_data_off_summary" msgid="3663995422004150567">"Los datos móviles no se conectarán automáticamente"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"Sin conexión"</string>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Al menos un dispositivo debe estar disponible"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Cambia de pantalla ahora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Abre el teléfono"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"¿Cambiar de pantalla?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para una mayor resolución, usa la cámara trasera"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para una mayor resolución, gira el teléfono"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable desplegándose"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo plegable mostrado desde varios ángulos"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Batería restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Ajustes de pantalla de bloqueo"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Red Wi-Fi no disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Cámara bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Cámara y micrófono bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrófono bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo Prioridad activado"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml
index cee83711077c..7451e6b9ada8 100644
--- a/packages/SystemUI/res/values-es/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Desactivado"</item>
<item msgid="5966994759929723339">"Activado"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"No disponible"</item>
+ <item msgid="2478289035899842865">"Desactivado"</item>
+ <item msgid="5137565285664080143">"Activado"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index b9d753e106cc..8aa73d00335f 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Kui sisestate järgmisel katsel vale PIN-koodi, kustutatakse teie tööprofiil ja selle andmed."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Kui sisestate järgmisel katsel vale parooli, kustutatakse teie tööprofiil ja selle andmed."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Puudutage sõrmejäljeandurit"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Sõrmejälje ikoon"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nägu ei õnnestu tuvastada. Kasutage sõrmejälge."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Märguande vari."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kiirseaded."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kiirseaded ja märguandeala."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kuva lukustamine."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Töö lukustuskuva"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Sulgemine"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Heledus"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Värvide ümberpööramine"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Värviparandus"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Fondi suurus"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Kasutajate haldamine"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Valmis"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Sule"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Alusta kohe"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Märguandeid pole"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Uusi märguandeid ei ole"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Uute märguannete nägemiseks avage"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Vanemate märguannete nägemiseks avage"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Seda seadet haldab sinu vanem"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Teie organisatsioon on selle seadme omanik ja võib jälgida võrguliiklust"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> on selle seadme omanik ja võib jälgida võrguliiklust"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekraanikuva salvest."</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Pealkiri puudub"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Ooterežiim"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Fondi suurus"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Vähendamine"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Suurendamine"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Suurendamisaken"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Suurendamisakna juhtelemendid"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Suumi sisse"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Lisati # juhtnupp.}other{Lisati # juhtnuppu.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Eemaldatud"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Kas lisada <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Kui lisate rakenduse <xliff:g id="APPNAME">%s</xliff:g>, saab see sellele paneelile lisada juhtelemendid ja sisu. Mõnes rakenduses saate valida, millised juhtelemendid siin kuvatakse."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Kas soovite rakenduse <xliff:g id="APPNAME">%s</xliff:g> juhtelemendid eemaldada?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Lisatud lemmikuks"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Lisatud lemmikuks, positsioon <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Eemaldatud lemmikute hulgast"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Muu"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Seadmete juhtimisvidinate hulka lisamine"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Lisa"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Eemalda"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Soovitas <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Seade on lukustatud"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Kas soovite seadmete juhtelemente lukustuskuval kuvada ja kasutada?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Võite lukustuskuvale oma väliste seadmete juhtelemendid lisada.\n\nTeie seadmerakendus võib võimaldada teil teatud seadmeid ilma telefoni või tahvelarvutit avamata hallata.\n\nSaate igal ajal seadetes muudatusi teha."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Kas soovite seadmeid lukustuskuva kaudu hallata?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Võite teatud seadmeid ilma telefoni või tahvelarvutit avamata hallata.\n\nTeie seadmerakendus määrab, milliseid seadmeid saab sel viisil hallata."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Tänan, ei"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Jah"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-kood sisaldab tähti või sümboleid"</string>
@@ -881,7 +881,8 @@
<string name="controls_error_failed" msgid="960228639198558525">"Ilmnes viga, proovige uuesti"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Lisa juhtelemente"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Muuda juhtelemente"</string>
- <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Rakenduse lisamine"</string>
+ <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Lisa rakendus"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Eemalda rakendus"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Väljundite lisamine"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupp"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 seade on valitud"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Vähemalt üks seade on saadaval"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Vaheta ekraane kohe"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Telefoni lahtivoltimine"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Kas vahetada ekraane?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Suurema eraldusvõime saavutamiseks kasutage tagakaamerat"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Suurema eraldusvõime saavutamiseks pöörake telefon ümber"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Volditava seadme lahtivoltimine"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Volditava seadme ümberpööramine"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akutase on <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Lülitu tööprofiilile"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Sule"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lukustuskuva seaded"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi pole saadaval"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kaamera on blokeeritud"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kaamera ja mikrofon on blokeeritud"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon on blokeeritud"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteetne režiim on sisse lülitatud"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/tiles_states_strings.xml b/packages/SystemUI/res/values-et/tiles_states_strings.xml
index 7bf520f581c3..6a9edbbe812a 100644
--- a/packages/SystemUI/res/values-et/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-et/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Väljas"</item>
<item msgid="5966994759929723339">"Sees"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Pole saadaval"</item>
+ <item msgid="2478289035899842865">"Väljas"</item>
+ <item msgid="5137565285664080143">"Sees"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 722bd7870146..e109235532bb 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Hurrengo saiakeran PINa oker idazten baduzu, laneko profila eta bertako datuak ezabatuko dira."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Hurrengo saiakeran pasahitza oker idazten baduzu, laneko profila eta bertako datuak ezabatuko dira."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sakatu hatz-marken sentsorea"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Hatz-markaren ikonoa"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ezin da hauteman aurpegia. Erabili hatz-marka."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Jakinarazpenen panela."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ezarpen bizkorrak."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ezarpen bizkorrak eta jakinarazpenen panela."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantaila blokeatzeko aukera."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Laneko pantaila blokeatua"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Itxi"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Distira"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Kolore-alderantzikatzea"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Koloreen zuzenketa"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Letra-tamaina"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Kudeatu erabiltzaileak"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Eginda"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Itxi"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"pantaila-grabaketa"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ez du izenik"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Egonean"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Letraren tamaina"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Txikitu"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Handitu"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Lupa-leihoa"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Lupa-leihoaren aukerak"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Handitu"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Kontrolatzeko # aukera gehitu da.}other{Kontrolatzeko # aukera gehitu dira.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Kenduta"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> gehitu nahi duzu?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> gehitzen duzunean, kontrolatzeko aukerak eta edukia gehi ditzake panelean. Aplikazio batzuetan, hemen zein kontrolatzeko aukera agertzen diren aukera dezakezu."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> kontrolatzeko aukerak kendu nahi dituzu?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Gogokoetan dago"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>. gogokoa da"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Ez dago gogokoetan"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Beste bat"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Gehitu gailuak kontrolatzeko widgetetan"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Gehitu"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Kendu"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> aplikazioak iradoki du"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Gailua blokeatuta"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Gailuak pantaila blokeatuan ikusi eta kontrolatu nahi dituzu?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Kanpoko gailuak kontrolatzeko aukerak gehi ditzakezu pantaila blokeatuan.\n\nBaliteke telefonoa edo tableta desblokeatu gabe gailu batzuk kontrolatzeko baimena ematea gailuaren aplikazioak.\n\nAldaketak egiteko, joan Ezarpenak atalera."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Gailuak pantaila blokeatuan kontrolatu nahi dituzu?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Gailu batzuk telefonoa edo tableta desblokeatu gabe kontrola ditzakezu.\n\nGailuaren aplikazioak zehaztuko du zer gailu kontrola daitezkeen modu horretan."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ez, eskerrik asko"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Bai"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN kodeak hizkiak edo ikurrak ditu"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Gehitu aukerak"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editatu aukerak"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Gehitu aplikazio bat"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Kendu aplikazioa"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Gehitu irteerak"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Taldea"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 gailu hautatu da"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Gutxienez gailu bat erabilgarri dago."</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Aldatu pantaila batetik bestera"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Ireki telefonoa"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Pantaila batetik bestera aldatu nahi duzu?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Erabili atzeko kamera bereizmen handiago a lortzeko"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Irauli telefonoa bereizmen handiago a lortzeko"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Gailu tolesgarria zabaltzen"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Gailu tolesgarria biratzen"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateriaren <xliff:g id="PERCENTAGE">%s</xliff:g> geratzen da"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Aldatu laneko profilera"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Itxi"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Pantaila blokeatuaren ezarpenak"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi-konexioa ez dago erabilgarri"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera blokeatuta dago"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera eta mikrofonoa blokeatuta daude"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonoa blokeatuta dago"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Lehentasun modua aktibatuta dago"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/tiles_states_strings.xml b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
index 333ede134f45..d023076ca2bf 100644
--- a/packages/SystemUI/res/values-eu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Desaktibatuta"</item>
<item msgid="5966994759929723339">"Aktibatuta"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ez dago erabilgarri"</item>
+ <item msgid="2478289035899842865">"Desaktibatuta"</item>
+ <item msgid="5137565285664080143">"Aktibatuta"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index fa7c5c6e9f9d..d373225f3ff3 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -93,7 +93,7 @@
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"مرز سمت راست <xliff:g id="PERCENT">%1$d</xliff:g> درصد"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"در برنامه <xliff:g id="APP">%1$s</xliff:g> در نمایه کاری ذخیره شد"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
- <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> این نماگرفت را تشخیص داد."</string>
+ <string name="screenshot_detected_template" msgid="7940376642921719915">"‫«<xliff:g id="APPNAME">%1$s</xliff:g>» این نماگرفت را تشخیص داد."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> و سایر برنامه‌های باز این نماگرفت را تشخیص دادند."</string>
<string name="screenrecord_name" msgid="2596401223859996572">"ضبط‌کننده صفحه‌نمایش"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"درحال پردازش ضبط صفحه‌نمایش"</string>
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"اگر در تلاش بعدی‌ پین نادرستی وارد کنید، نمایه کاری شما و داده‌های آن حذف خواهند شد."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"اگر در تلاش بعدی‌ گذرواژه نادرستی وارد کنید، نمایه کاری شما و داده‌های آن حذف خواهند شد."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"حسگر اثر انگشت را لمس کنید"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"نماد اثر انگشت"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"چهره شناسایی نشد. درعوض از اثر انگشت استفاده کنید."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -187,8 +186,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"باتری <xliff:g id="NUMBER">%d</xliff:g> درصد."</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"درصد شارژ باتری: <xliff:g id="PERCENTAGE">%1$d</xliff:g>، <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"در حال شارژ باتری، <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> درصد"</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"درصد شارژ باتری: <xliff:g id="PERCENTAGE">%d</xliff:g>، شارژ شدن برای محافظت از باتری موقتاً متوقف شد."</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"درصد شارژ باتری: <xliff:g id="PERCENTAGE">%1$d</xliff:g>، <xliff:g id="TIME">%2$s</xliff:g>، شارژ شدن برای محافظت از باتری موقتاً متوقف شد."</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"شارژ باتری <xliff:g id="PERCENTAGE">%d</xliff:g> درصد است. شارژ شدن برای محافظت از باتری موقتاً متوقف شد."</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"شارژ باتری <xliff:g id="PERCENTAGE">%1$d</xliff:g> درصد، <xliff:g id="TIME">%2$s</xliff:g>. شارژ شدن برای محافظت از باتری موقتاً متوقف شد."</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"دیدن همه اعلان‌ها"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"تله‌تایپ فعال شد."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"زنگ لرزشی."</string>
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"صفحه قفل کاری"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"بستن"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"روشنایی"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"وارونگی رنگ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"تصحیح رنگ"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"اندازه قلم"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"مدیریت کاربران"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"تمام"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"بستن"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ضبط صفحه‌نمایش"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"بدون عنوان"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"آماده‌به‌کار"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"اندازه قلم"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"کوچک‌تر کردن"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"بزرگ‌تر کردن"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"پنجره درشت‌نمایی"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"کنترل‌های پنجره درشت‌نمایی"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"زوم‌پیش کردن"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# کنترل اضافه شد.}one{# کنترل اضافه شد.}other{# کنترل اضافه شد.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"حذف شد"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> افزوده شود؟"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"وقتی <xliff:g id="APPNAME">%s</xliff:g> را اضافه می‌کنید، می‌تواند کنترل‌ها و محتوا را به این پانل اضافه کند. در برخی‌از برنامه‌ها می‌توانید انتخاب کنید چه کنترل‌هایی در اینجا نشان داده شود."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"کنترل‌های <xliff:g id="APPNAME">%s</xliff:g> برداشته شود؟"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"به موارد دلخواه اضافه شد"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"اضافه‌شده به موارد دلخواه، جایگاه <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"حذف‌شده از موارد دلخواه"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"موارد دیگر"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"افزودن به کنترل‌های دستگاه"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"افزودن"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"برداشتن"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"پیشنهاد <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"دستگاه قفل است"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"امکان دیدن و کنترل دستگاه‌ها از صفحه قفل وجود داشته باشد؟"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"می‌توانید کنترل‌هایی برای دستگاه‌های خارجی به صفحه قفل اضافه کنید.\n\nبرنامه دستگاهتان ممکن است به شما اجازه دهد بعضی‌از دستگاه‌ها را بدون باز کردن قفل تلفن یا رایانه لوحی‌تان کنترل کنید.\n\nهرزمان بخواهید می‌توانید در «تنظیمات» تغییراتی اعمال کنید."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"امکان کنترل دستگاه‌ها از صفحه قفل وجود داشته باشد؟"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"می‌توانید بعضی‌از دستگاه‌ها را بدون باز کردن قفل تلفن یا رایانه لوحی‌تان کنترل کنید.\n\nبرنامه دستگاهتان تعیین می‌کند کدام دستگاه‌ها را می‌توان به این روش کنترل کرد."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"نه متشکرم"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"بله"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"پین شامل حروف یا نماد است"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"افزودن کنترل‌ها"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ویرایش کنترل‌ها"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"افزودن برنامه"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"برداشتن برنامه"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"افزودن خروجی"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"گروه"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"۱ دستگاه انتخاب شد"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• حداقل یک دستگاه دردسترس باشد"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"میان‌بر را لمس کنید و نگه دارید"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"لغو کردن"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"صفحه‌ها اکنون جابه‌جا می‌شود"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"باز کردن تلفن"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"صفحه‌ها جابه‌جا شود؟"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"برای وضوح بیشتر، از دوربین پشت استفاده کنید"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"برای وضوح بیشتر، تلفن را برگردانید"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"دستگاه تاشو درحال باز شدن"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"دستگاه تاشو درحال چرخش به اطراف"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> باتری باقی مانده است"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"رفتن به نمایه کاری"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"بستن"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"تنظیمات صفحه قفل"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏Wi-Fi دردسترس نیست"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"دوربین مسدود شده است"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"دوربین و میکروفون مسدود شده‌اند"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"میکروفون مسدود شده است"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"حالت اولویت روشن است"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/tiles_states_strings.xml b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
index 436ea31f2044..b341e9e64c7b 100644
--- a/packages/SystemUI/res/values-fa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"خاموش"</item>
<item msgid="5966994759929723339">"روشن"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"دردسترس نیست"</item>
+ <item msgid="2478289035899842865">"خاموش"</item>
+ <item msgid="5137565285664080143">"روشن"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 7191d6c63126..bc0774924066 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -28,7 +28,7 @@
<string name="invalid_charger_text" msgid="2339310107232691577">"Käytä laitteesi mukana tullutta laturia"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Otetaanko virransäästö käyttöön?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Tietoa virransäästöstä"</string>
- <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Ota käyttöön"</string>
+ <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Laita päälle"</string>
<string name="battery_saver_start_action" msgid="8353766979886287140">"Laita päälle"</string>
<string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ei kiitos"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Näytön automaattinen kääntö"</string>
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jos annat väärän PIN-koodin seuraavalla yrityskerralla, työprofiilisi ja sen data poistetaan."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Jos annat väärän salasanan seuraavalla yrityskerralla, työprofiilisi ja sen data poistetaan."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Kosketa sormenjälkitunnistinta"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Sormenjälkikuvake"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Kasvoja ei voi tunnistaa. Käytä sormenjälkeä."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Ilmoitusalue."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Pika-asetukset."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Pika-asetukset ja ilmoitusalue"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lukitse näyttö."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Työlukitusnäyttö"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Sulje"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Kirkkaus"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Käänteiset värit"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Värinkorjaus"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Fonttikoko"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Ylläpidä käyttäjiä"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Valmis"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Sulje"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Aloita nyt"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Ei ilmoituksia"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Ei uusia ilmoituksia"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Avaa lukitus uusia ilmoituksia varten"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Avaa lukitus niin näet ilmoituksia"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Vanhempasi ylläpitää tätä laitetta"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisaatiosi omistaa laitteen ja voi valvoa verkkoliikennettä"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> omistaa laitteen ja voi valvoa verkkoliikennettä"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"näytön tallennus"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ei nimeä"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Virransäästötila"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Fonttikoko"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Pienennä"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Suurenna"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Suurennusikkuna"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Suurennusikkunan ohjaimet"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Lähennä"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# säädin lisätty.}other{# säädintä lisätty.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Poistettu"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Lisätäänkö <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Kun <xliff:g id="APPNAME">%s</xliff:g> lisätään, se voi lisätä asetuksia ja sisältöä tähän paneeliin. Joissakin sovelluksissa voit valita, mitä asetukset näkyvät täällä."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Poistetaanko säätimet: <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Lisätty suosikkeihin"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Lisätty suosikkeihin sijalle <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Poistettu suosikeista"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Muu"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Lisää laitteiden hallintaan"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Lisää"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Poista"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Ehdottaja: <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Laite lukittu"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Haluatko nähdä ja hallita laitteita lukitusnäytöltä?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Voit lisätä lukitusnäytölle ohjaimia ulkoisia laitteita varten.\n\nLaitteen sovellus voi sallia joidenkin laitteiden ohjaamisen avaamatta puhelimen tai tabletin lukitusta.\n\nVoit milloin tahansa tehdä muutoksia asetuksissa."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Haluatko ohjata laitteita lukitusnäytöllä?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Voit ohjata joitakin laitteita avaamatta puhelimen tai tabletin lukitusta.\n\nRiippuu laitteen sovelluksesta, mitä laitteita voi ohjata näin."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ei kiitos"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Kyllä"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-koodi sisältää kirjaimia tai symboleja"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Lisää säätimiä"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Muokkaa säätimiä"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Lisää sovellus"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Poista sovellus"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Lisää toistotapoja"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Ryhmä"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 laite valittu"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Ei voi lähettää"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Käytä vähintään 4 merkkiä"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Käytä alle 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ainakin yksi laite on käytettävissä"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Vaihda näyttöä nyt"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Taita puhelin auki"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vaihdetaanko näyttöä?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Resoluutio on parempi, kun käytät takakameraa"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Resoluutio on parempi, kun käännät puhelimen"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Taitettava laite taitetaan"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Taitettava laite käännetään ympäri"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akkua jäljellä <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Vaihda työprofiiliin"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Sulje"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lukitusnäytön asetukset"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi-yhteys ei ole käytettävissä"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera estetty"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera ja mikrofoni estetty"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofoni estetty"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Tärkeät-tila on päällä"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/tiles_states_strings.xml b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
index 4bec4b3157cb..bbd64fdb87da 100644
--- a/packages/SystemUI/res/values-fi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Poissa päältä"</item>
<item msgid="5966994759929723339">"Päällä"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ei saatavilla"</item>
+ <item msgid="2478289035899842865">"Pois päältä"</item>
+ <item msgid="5137565285664080143">"Päällä"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index dbd35189a4f2..5c63abd03665 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Si vous entrez un NIP incorrect à la prochaine tentative, votre profil professionnel et ses données seront supprimés."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Si vous entrez un mot de passe incorrect à la prochaine tentative suivante, votre profil professionnel et ses données seront supprimés."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touchez le capteur d\'empreintes digitales"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icône d\'empreinte digitale"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Visage non reconnu. Utilisez plutôt l\'empreinte digitale."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Volet des notifications"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Paramètres rapides"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Paramètres rapides et volet des notifications."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Écran de verrouillage"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Verrouillage de l\'écran du profil professionnel"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fermer"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminosité"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversion des couleurs"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correction des couleurs"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Taille de la police"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gérer les utilisateurs"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Terminé"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Fermer"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"enregistrement d\'écran"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Veille"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Taille de police"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Rapetisser"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Agrandir"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Commandes pour la fenêtre d\'agrandissement"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Effectuer un zoom avant"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# commande ajoutée.}one{# commande ajoutée.}many{# de commandes ajoutées.}other{# commandes ajoutées.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Ajouter <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Lorsque vous ajoutez <xliff:g id="APPNAME">%s</xliff:g>, elle peut ajouter des commandes et du contenu à ce panneau. Dans certaines applications, vous pouvez choisir les commandes qui s\'affichent ici."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Retirer les commandes pour <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Ajouté aux favoris"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ajouté aux favoris, en position <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Supprimé des favoris"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Autre"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Ajouter aux commandes des appareils"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Ajouter"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Retirer"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Suggestion de <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Appareil verrouillé"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Afficher et contrôler les appareils à partir de l\'écran de verrouillage?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Vous pouvez ajouter des commandes pour vos appareils externes à l\'écran de verrouillage.\n\nL\'application de votre appareil peut vous permettre de contrôler certains appareils sans déverrouiller votre téléphone ou votre tablette.\n\nVous pouvez apporter des modifications à tout moment dans les paramètres."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Contrôler les appareils à partir de l\'écran de verrouillage?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Vous pouvez contrôler certains appareils sans déverrouiller votre téléphone ou votre tablette.\n\nL\'application de votre appareil détermine quels appareils peuvent être contrôlés de cette manière."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Non merci"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Oui"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Le NIP contient des lettres ou des symboles"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Ajouter des commandes"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Modifier des commandes"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ajouter une application"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Retirer l\'application"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ajouter des sorties"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Groupe"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Un appareil sélectionné"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Impossible de diffuser"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilisez au moins 4 caractères"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilisez moins de 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• qu\'au moins un appareil est utilisable;"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Changer d\'écran maintenant"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Déplier le téléphone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Changer d\'écran?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Pour une meilleure résolution, utilisez l\'appareil photo arrière"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Pour une meilleure résolution, retournez le téléphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Appareil pliable en cours de dépliage"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Appareil pliable en train d\'être retourné"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Charge restante de la pile : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Passer au profil professionnel"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Fermer"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Paramètres écran de verrouillage"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non accessible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Appareil photo bloqué"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Appareil photo et microphone bloqués"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone bloqué"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode Priorité activé"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
index 788f56de1bdc..8df62113b674 100644
--- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Désactivé"</item>
<item msgid="5966994759929723339">"Activé"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Non accessible"</item>
+ <item msgid="2478289035899842865">"Désactivée"</item>
+ <item msgid="5137565285664080143">"Activée"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index ff8c44fe6e7b..23448b2f1a35 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Si vous saisissez un code incorrect lors de la prochaine tentative, votre profil professionnel et les données associées seront supprimés."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Si vous saisissez un mot de passe incorrect lors de la prochaine tentative, votre profil professionnel et les données associées seront supprimés."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Appuyez sur le lecteur d\'empreinte digitale"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icône d\'empreinte digitale"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Visage non reconnu. Utilisez votre empreinte."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Volet des notifications"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Réglages rapides"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Réglages rapides et volet des notifications."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Écran de verrouillage"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Écran de verrouillage du profil professionnel"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fermer"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminosité"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversion des couleurs"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correction des couleurs"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Taille de la police"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gérer les utilisateurs"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"OK"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Fermer"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"enregistrement écran"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Mode Veille imminent"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Taille de police"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Réduire"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Agrandir"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Fenêtre des commandes d\'agrandissement"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Faire un zoom avant"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# commande ajoutée.}one{# commande ajoutée.}many{# commandes ajoutées.}other{# commandes ajoutées.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Ajouter <xliff:g id="APPNAME">%s</xliff:g> ?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Lorsque vous ajoutez l\'appli <xliff:g id="APPNAME">%s</xliff:g>, elle peut ajouter des commandes et contenus dans ce panneau. Dans certaines applis, vous pouvez choisir les commandes à afficher ici."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Supprimer les commandes pour <xliff:g id="APPNAME">%s</xliff:g> ?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Ajouté aux favoris"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ajouté aux favoris, en position <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Supprimé des favoris"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Autre"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Ajouter aux commandes des appareils"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Ajouter"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Supprimer"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Suggérée par <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Appareil verrouillé"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Afficher et contrôler les appareils depuis l\'écran de verrouillage ?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Vous pouvez ajouter des commandes pour vos appareils externes sur l\'écran de verrouillage.\n\nL\'appli de votre appareil peut vous autoriser à contrôler certains appareils sans déverrouiller votre téléphone ou tablette.\n\nVous pouvez apporter des modifications à tout moment dans les paramètres."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Contrôler des appareils depuis l\'écran de verrouillage ?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Vous pouvez contrôler certains appareils sans déverrouiller votre téléphone ou tablette.\n\nL\'appli de votre appareil détermine les appareils qui peuvent être contrôlés de cette manière."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Non, merci"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Oui"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Le code contient des lettres ou des symboles"</string>
@@ -876,12 +876,13 @@
<string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Commande indisponible"</string>
<string name="controls_error_removed_message" msgid="2885911717034750542">"Impossible d\'accéder à \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Vérifiez l\'application <xliff:g id="APPLICATION">%2$s</xliff:g> pour vous assurer que la commande est toujours disponible et que les paramètres de l\'application n\'ont pas changé."</string>
- <string name="controls_open_app" msgid="483650971094300141">"Ouvrir l\'application"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Ouvrir l\'appli"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Impossible de charger l\'état"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Erreur. Veuillez réessayer."</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Ajouter des commandes"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Modifier des commandes"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ajouter une appli"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Supprimer l\'application"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ajouter des sorties"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Groupe"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 appareil sélectionné"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Impossible de diffuser"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilisez au moins quatre caractères"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilisez moins de 16 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>
@@ -963,7 +962,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Données mobiles"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Connecté"</string>
- <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connectée temporairement"</string>
+ <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connexion temporaire"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Connexion médiocre"</string>
<string name="mobile_data_off_summary" msgid="3663995422004150567">"Pas de connexion automatique des données mobiles"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"Aucune connexion"</string>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Au moins un appareil est disponible"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Changer d\'écran maintenant"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Déplier le téléphone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Changer d\'écran ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Pour une résolution plus élevée, utilisez la caméra arrière"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Pour une résolution plus élevée, retournez le téléphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Appareil pliable qui est déplié"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Appareil pliable qui est retourné"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> de batterie restante"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Passer au profil professionnel"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Fermer"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Paramètres écran de verrouillage"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Caméra bloquée"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Caméra et micro bloqués"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micro bloqué"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode Prioritaire activé"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
index 3f63a9639a80..ce39cd2dc78d 100644
--- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Désactivé"</item>
<item msgid="5966994759929723339">"Activé"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Non disponible"</item>
+ <item msgid="2478289035899842865">"Désactivé"</item>
+ <item msgid="5137565285664080143">"Activé"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 62d0a3082b58..945faeafb450 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Se indicas un PIN incorrecto no seguinte intento, eliminaranse o teu perfil de traballo e os datos asociados."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Se indicas un contrasinal incorrecto no seguinte intento, eliminaranse o teu perfil de traballo e os datos asociados."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca o sensor de impresión dixital"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icona de impresión dixital"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Non se recoñeceu a cara. Usa a impresión dixital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel despregable"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuración rápida"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuración rápida e panel despregable."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueo do perfil de traballo"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Pechar"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillo"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversión da cor"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corrección da cor"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamaño do tipo de letra"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Administrar usuarios"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Feito"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Pechar"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Non hai notificacións"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Non hai notificacións novas"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notificacións"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver máis notificacións"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"O teu pai ou nai xestiona este dispositivo"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"A túa organización é propietaria deste dispositivo e pode controlar o tráfico de rede"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é a organización propietaria deste dispositivo e pode controlar o tráfico de rede"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"gravación pantalla"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sen título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Modo de espera"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamaño do tipo de letra"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Reducir o tamaño"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar o tamaño"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventá de superposición"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controis de ampliación da ventá"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Achegar"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Engadiuse # control.}other{Engadíronse # controis.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Quitouse"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Queres engadir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Cando engadas a aplicación <xliff:g id="APPNAME">%s</xliff:g>, poderá incluír controis e contido neste panel Nalgunhas aplicacións, podes escoller os controis que se mostrarán aquí."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Queres quitar os controis de <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Está entre os controis favoritos"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Está entre os controis favoritos (posición: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Non está entre os controis favoritos"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outra"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Engadir ao control de dispositivos"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Engadir"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Quitar"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Control suxerido por <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Disposit. bloqueado"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Queres que se mostren dispositivos na pantalla de bloqueo e poder controlalos desde ela?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Podes engadir á pantalla de bloqueo controis para os dispositivos externos.\n\nÉ posible que a aplicación do dispositivo che permita controlar algúns dispositivos sen desbloquear o teléfono ou a tableta.\n\nPodes realizar cambios cando queiras en Configuración."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Queres controlar dispositivos desde a pantalla de bloqueo?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Podes controlar algúns dispositivos sen desbloquear o teléfono ou a tableta.\n\nA aplicación do dispositivo determina os dispositivos que se poden controlar deste xeito."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Non, grazas"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Si"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contén letras ou símbolos"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Engadir controis"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controis"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Engadir aplicación"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Quitar aplicación"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Engadir saídas"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Seleccionouse 1 dispositivo"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Non se puido iniciar a emisión"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utiliza como mínimo 4 caracteres"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utiliza menos de 16 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>
@@ -1032,16 +1031,11 @@
<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_press_too_short" msgid="8145437175134998864">"Mantén premido o atallo"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Cambiar de pantalla agora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Desprega o teléfono"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Queres cambiar de pantalla?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Usa a cámara traseira para gozar dunha maior resolución"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Dálle a volta ao teléfono para gozar dunha maior resolución"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo pregable abríndose"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo pregable xirando"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Batería restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar ao perfil de traballo"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Pechar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Configuración pantalla bloqueo"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi non dispoñible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"A cámara está bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"A cámara e o micrófono están bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"O micrófono está bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"O modo de prioridade está activado"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/tiles_states_strings.xml b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
index 94fc3f487d17..b03f31171e5c 100644
--- a/packages/SystemUI/res/values-gl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Desactivado"</item>
<item msgid="5966994759929723339">"Activado"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Non dispoñible"</item>
+ <item msgid="2478289035899842865">"Desactivado"</item>
+ <item msgid="5137565285664080143">"Activado"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index ab37dbb011a5..b9822052272e 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"જો તમે આગલા પ્રયત્નમાં ખોટો પિન દાખલ કરશો, તો તમારી કાર્યાલયની પ્રોફાઇલ અને તેનો ડેટા ડિલીટ કરવામાં આવશે."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"જો તમે આગલા પ્રયત્નમાં ખોટો પાસવર્ડ દાખલ કરશો, તો તમારી કાર્યાલયની પ્રોફાઇલ અને તેનો ડેટા ડિલીટ કરવામાં આવશે."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ફિંગરપ્રિન્ટના સેન્સરને સ્પર્શ કરો"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ફિંગરપ્રિન્ટનું આઇકન"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ચહેરો ઓળખી શકતા નથી. તેને બદલે ફિંગરપ્રિન્ટ વાપરો."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"કાર્ય લૉક સ્ક્રીન"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"બંધ કરો"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"તેજ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"વિપરીત રંગમાં બદલવું"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"રંગ સુધારણા"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ફૉન્ટનું કદ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"વપરાશકર્તાઓને મેનેજ કરો"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"થઈ ગયું"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"બંધ કરો"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"સ્ક્રીન રેકોર્ડિંગ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"કોઈ શીર્ષક નથી"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"સ્ટૅન્ડબાય"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ફૉન્ટનું કદ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"વધુ નાનું બનાવો"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"વધુ મોટું બનાવો"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"વિસ્તૃતીકરણ વિંડો"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"વિસ્તૃતીકરણ વિંડોના નિયંત્રણો"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"મોટું કરો"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# નિયંત્રણ ઉમેર્યું.}one{# નિયંત્રણ ઉમેર્યું.}other{# નિયંત્રણ ઉમેર્યા.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"કાઢી નાખ્યું"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ઉમેરીએ?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"જ્યારે તમે <xliff:g id="APPNAME">%s</xliff:g> ઉમેરો, ત્યારે તે આ પૅનલમાં નિયંત્રણો અને કન્ટેન્ટ ઉમેરી શકે છે. કેટલીક ઍપમાં, અહીં કયા નિયંત્રણો દેખાય તે તમે પસંદ કરી શકો છો."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> માટે નિયંત્રણો કાઢી નાખીએ?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"મનપસંદમાં ઉમેર્યું"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"મનપસંદમાં ઉમેર્યું, સ્થાન <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"મનપસંદમાંથી કાઢી નાખ્યું"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"અન્ય"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ડિવાઇસનાં નિયંત્રણોમાં ઉમેરો"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ઉમેરો"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"કાઢી નાખો"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> દ્વારા સૂચવેલા"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"ડિવાઇસ લૉક કરેલું છે"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"લૉક સ્ક્રીનમાંથી ડિવાઇસ બતાવીએ અને નિયંત્રિત કરીએ?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"તમે તમારા બાહ્ય ડિવાઇસ માટેના નિયંત્રણો લૉક સ્ક્રીન પર ઉમેરી શકો છો.\n\nતમારી ડિવાઇસ ઍપ કદાચ તમને તમારો ફોન કે ટૅબ્લેટ અનલૉક કર્યા વિના અમુક ડિવાઇસ નિયંત્રિત કરવાની મંજૂરી આપી શકે.\n\nતમે ગમે ત્યારે સેટિંગમાં જઈને ફેરફાર કરી શકો છો."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"લૉક સ્ક્રીનમાંથી ડિવાઇસ નિયંત્રિત કરીએ?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"તમે તમારા ફોન કે ટૅબ્લેટને અનલૉક કર્યા વિના અમુક ડિવાઇસ નિયંત્રિત કરી શકો છો.\n\nતમારી ડિવાઇસ ઍપ નક્કી કરે છે કે આ રીતે કયા ડિવાઇસને નિયંત્રિત કરવા."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ના, આભાર"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"હા"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"પિનમાં અક્ષરો અથવા પ્રતીકોનો સમાવેશ થાય છે"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"નિયંત્રણો ઉમેરો"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"નિયંત્રણોમાં ફેરફાર કરો"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"ઍપ ઉમેરો"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"ઍપ કાઢી નાખો"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"આઉટપુટ ઉમેરો"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"ગ્રૂપ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ડિવાઇસ પસંદ કર્યું"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"બ્રોડકાસ્ટ કરી શકતા નથી"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"સાચવી શકતા નથી. ફરી પ્રયાસ કરો."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"સાચવી શકતા નથી."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ઓછામાં ઓછા 4 અક્ષરનો ઉપયોગ કરો"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 કરતાં ઓછા અક્ષરનો ઉપયોગ કરો"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ઓછામાં ઓછું એક ડિવાઇસ ઉપલબ્ધ છે"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"શૉર્ટકટને ટચ વડે પળભર દબાવી રાખો"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"રદ કરો"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"હમણાં સ્ક્રીન સ્વિચ કરો"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ફોનને અનફોલ્ડ કરો"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"સ્ક્રીન સ્વિચ કરીએ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"વધુ રિઝોલ્યુશન માટે, રીઅર કૅમેરાનો ઉપયોગ કરો"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"વધુ રિઝોલ્યુશન માટે, ફોનને ફ્લિપ કરો"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ફોલ્ડ કરી શકાય એવું ડિવાઇસ અનફોલ્ડ કરવામાં આવી રહ્યું છે"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ફોલ્ડ કરી શકાય એવું ડિવાઇસ ફ્લિપ કરવામાં આવી રહ્યું છે"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> બૅટરી બાકી છે"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ઑફિસની પ્રોફાઇલ પર સ્વિચ કરો"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"બંધ કરો"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"લૉક સ્ક્રીનના સેટિંગ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"વાઇ-ફાઇ ઉપલબ્ધ નથી"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"કૅમેરા બ્લૉક કરેલો છે"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"કૅમેરા અને માઇક્રોફોન બ્લૉક કરેલા છે"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"માઇક્રોફોન બ્લૉક કરેલો છે"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"પ્રાધાન્યતા મોડ ચાલુ છે"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
index e92168c37cb8..5d1ad6ff0514 100644
--- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"બંધ છે"</item>
<item msgid="5966994759929723339">"ચાલુ છે"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"અનુપલબ્ધ"</item>
+ <item msgid="2478289035899842865">"બંધ"</item>
+ <item msgid="5137565285664080143">"ચાલુ"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 22933ba04605..87f5edd97edb 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"अगर आप फिर से गलत पिन डालते हैं, तो आपकी वर्क प्रोफ़ाइल और उसका डेटा मिटा दिया जाएगा."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"अगर आप फिर से गलत पासवर्ड डालते हैं, तो आपकी वर्क प्रोफ़ाइल और उसका डेटा मिटा दिया जाएगा."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"फ़िंगरप्रिंट सेंसर को छुएं"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"फ़िंगरप्रिंट आइकॉन"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"चेहरे की पहचान नहीं हुई. फ़िंगरप्रिंट इस्तेमाल करें."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"वर्क लॉक स्‍क्रीन"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करें"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"स्क्रीन की रोशनी"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"रंग बदलने की सुविधा"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"रंग में सुधार करने की सुविधा"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"फ़ॉन्ट का साइज़"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"उपयोगकर्ताओं को मैनेज करें"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"हो गया"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"रद्द करें"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"स्क्रीन रिकॉर्डिंग"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"कोई शीर्षक नहीं"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"स्टैंडबाई"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"फ़ॉन्ट का साइज़"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"छोटा करें"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"बड़ा करें"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"स्क्रीन को बड़ा करके दिखाने वाली विंडो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"स्क्रीन को बड़ा करके दिखाने वाली विंडो के नियंत्रण"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ज़ूम इन करें"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# कंट्रोल जोड़ा गया.}one{# कंट्रोल जोड़ा गया.}other{# कंट्रोल जोड़े गए.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"हटाया गया"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> को जोड़ना है?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> को जोड़ने पर, वह इस पैनल पर कुछ कंट्रोल और कॉन्टेंट दिखा सकता है. कुछ ऐप्लिकेशन के लिए यह चुना जा सकता है कि वे इस पैनल पर कौनसे कंट्रोल दिखाएं."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> के लिए कंट्रोल हटाने हैं?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"पसंदीदा बनाया गया"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"पसंदीदा बनाया गया, क्रम संख्या <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"पसंदीदा से हटाया गया"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"अन्य"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"डिवाइस कंट्रोल में जोड़ें"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"जोड़ें"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"हटाएं"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> से मिला सुझाव"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"डिवाइस लॉक है"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"क्या डिवाइसों को लॉक स्क्रीन पर देखना है और उन्हें वहीं से कंट्रोल करना है?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"लॉक स्क्रीन पर अपने बाहरी डिवाइसों के लिए कंट्रोल जोड़े जा सकते हैं.\n\nअपने डिवाइस के ऐप्लिकेशन से कुछ डिवाइसों को कंट्रोल किया जा सकता है. इसके लिए, फ़ोन या टैबलेट को अनलॉक नहीं करना पड़ता.\n\nकिसी भी समय सेटिंग में जाकर बदलाव किए जा सकते हैं."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"क्या लॉक स्क्रीन से डिवाइसों को कंट्रोल करना है?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"फ़ोन या टैबलेट को अनलॉक किए बिना, कुछ डिवाइसों को कंट्रोल किया जा सकता है.\n\nआपके डिवाइस के ऐप्लिकेशन से यह तय किया जाता है कि किन डिवाइसों को इस तरह कंट्रोल किया जा सकता है."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"नहीं, रहने दें"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"हां"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"पिन में अक्षर या चिह्न शामिल होते हैं"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"कंट्राेल जोड़ें"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"कंट्रोल में बदलाव करें"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"ऐप्लिकेशन जोड़ें"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"ऐप्लिकेशन हटाएं"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट जोड़ें"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"ग्रुप"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"एक डिवाइस चुना गया"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• कम से कम एक डिवाइस उपलब्ध है"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"शॉर्टकट को दबाकर रखें"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द करें"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"अब स्क्रीन स्विच करें"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"अपना फ़ोन अनफ़ोल्ड करें"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"स्क्रीन स्विच करनी है?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"बेहतर रिज़ॉल्यूशन वाली फ़ोटो खींचने के लिए, पीछे का कैमरा इस्तेमाल करें"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"बेहतर रिज़ॉल्यूशन वाली फ़ोटो खींचने के लिए, फ़ोन को फ़्लिप करें"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फ़ोल्ड किया जा सकने वाला डिवाइस अनफ़ोल्ड किया जा रहा है"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फ़ोल्ड किया जा सकने वाला डिवाइस पलटा जा रहा है"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> बैटरी बची है"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"वर्क प्रोफ़ाइल पर स्विच करें"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"बंद करें"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"लॉक स्क्रीन की सेटिंग"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"वाई-फ़ाई उपलब्ध नहीं है"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"कैमरे का ऐक्सेस नहीं है"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"कैमरे और माइक्रोफ़ोन का ऐक्सेस नहीं है"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"माइक्रोफ़ोन का ऐक्सेस नहीं है"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राथमिकता मोड चालू है"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/tiles_states_strings.xml b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
index 0abf8b31ca1a..cd29fb92063f 100644
--- a/packages/SystemUI/res/values-hi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"बंद है"</item>
<item msgid="5966994759929723339">"चालू है"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"अभी उपलब्ध नहीं है"</item>
+ <item msgid="2478289035899842865">"बंद है"</item>
+ <item msgid="5137565285664080143">"चालू है"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 5de0d542cbe0..d0c9ebb7ee6e 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ako pri sljedećem pokušaju unesete netočan PIN, izbrisat će se vaš poslovni profil i njegovi podaci."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ako pri sljedećem pokušaju unesete netočnu zaporku, izbrisat će se vaš poslovni profil i njegovi podaci."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dodirnite senzor otiska prsta"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona otiska prsta"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Prepoznavanje lica nije uspjelo. Upotrijebite otisak prsta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Zaslon obavijesti."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Brze postavke."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brze postavke i zaslon obavijesti."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaključavanje zaslona."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan zaslon radnog profila"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvaranje"</string>
@@ -778,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"snimanje zaslona"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje mirovanja"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Veličina fonta"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Smanji"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Povećaj"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za povećavanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za povećavanje"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Povećaj"</string>
@@ -810,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Dodana je # kontrola.}one{Dodana je # kontrola.}few{Dodane su # kontrole.}other{Dodano je # kontrola.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Uklonjeno"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Želite li dodati aplikaciju <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Kada dodate aplikaciju <xliff:g id="APPNAME">%s</xliff:g>, može dodati kontrole i sadržaj na ovu ploču. U nekim aplikacijama možete odabrati koje se kontrole prikazuju ovdje."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Ukloniti kontrole za aplikaciju <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano u favorite"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano u favorite, položaj <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Uklonjeno iz favorita"</string>
@@ -828,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Dodavanje kontrolama uređaja"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Ukloni"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Preporuka s kanala <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Uređaj je zaključan"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Prikazati uređaje i omogućiti upravljanje njima na zaključanom zaslonu?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Na zaključan zaslon možete dodati kontrole za svoje vanjske uređaje.\n\nAplikacija vašeg uređaja može vam dopustiti upravljanje nekim uređajima bez otključavanja telefona ili tableta.\n\nPromjene uvijek možete unijeti u Postavkama."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Upravljati uređajima na zaključanom zaslonu?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Nekim uređajima možete upravljati bez otključavanja telefona ili tableta.\n\nAplikacija vašeg uređaja odlučuje kojim se uređajima može upravljati na taj način."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, hvala"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Da"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN sadrži slova ili simbole"</string>
@@ -875,12 +876,13 @@
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
<string name="controls_error_removed_message" msgid="2885911717034750542">"Nije moguće pristupiti uređaju: <xliff:g id="DEVICE">%1$s</xliff:g>. U aplikaciji <xliff:g id="APPLICATION">%2$s</xliff:g> provjerite je li kontrola i dalje dostupna te potvrdite da se postavke aplikacije nisu promijenile."</string>
- <string name="controls_open_app" msgid="483650971094300141">"Otvori apl."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Otvori aplikaciju"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Status se ne može učitati"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Pogreška, pokušajte ponovo"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrole"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Uredi kontrole"</string>
- <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodavanje aplikacije"</string>
+ <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikaciju"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Ukloni aplikaciju"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodavanje izlaza"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Odabran je jedan uređaj"</string>
@@ -1045,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Prijeđite na poslovni profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Postavke zaključanog zaslona"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nije dostupan"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Blokirani su kamera i mikrofon"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Uključen je prioritetni način rada"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index ffeeb14a3e74..79742efe5dd6 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Amennyiben helytelen PIN-kódot ad meg a következő kísérletnél, a rendszer törli munkaprofilját és a kapcsolódó adatokat."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Amennyiben helytelen jelszót ad meg a következő kísérletnél, a rendszer törli munkaprofilját és a kapcsolódó adatokat."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Érintse meg az ujjlenyomat-érzékelőt"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ujjlenyomat ikonja"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Az arc nem felismerhető. Használjon ujjlenyomatot."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Értesítési felület."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Gyorsbeállítások."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Gyorsbeállítások és értesítési terület"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lezárási képernyő."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Munka lezárási képernyővel"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Bezárás"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Fényerő"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Színek invertálása"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Színjavítás"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Betűméret"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Felhasználók kezelése"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Kész"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Bezárás"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"képernyőrögzítés"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nincs cím"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Készenléti mód"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Betűméret"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Kisebb"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Nagyobb"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Nagyítás ablaka"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Nagyítási vezérlők ablaka"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Nagyítás"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# vezérlő hozzáadva.}other{# vezérlő hozzáadva.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Eltávolítva"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Hozzáadja a(z) <xliff:g id="APPNAME">%s</xliff:g> alkalmazást?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"A(z) <xliff:g id="APPNAME">%s</xliff:g> hozzáadását követően az alkalmazás vezérlőelemeket és tartalmakat adhat hozzá ehhez a panelhez. Egyes alkalmazásokban kiválasztható, hogy mely vezérlőelemek jelenjenek meg itt."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Eltávolítja a(z) <xliff:g id="APPNAME">%s</xliff:g> vezérlőit?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Hozzáadva a kedvencekhez"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Hozzáadva a kedvencekhez <xliff:g id="NUMBER">%d</xliff:g>. helyen"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Eltávolítva a kedvencek közül"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Más"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Hozzáadás az eszközvezérlőkhöz"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Hozzáadás"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Eltávolítás"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> javasolta"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Az eszköz zárolva van"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Szeretne megtekinteni és vezérelni eszközöket a lezárási képernyőn?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Hozzáadhatja külső eszközök vezérlőit a lezárási képernyőhöz.\n\nAz eszközön lévő alkalmazás segítségével telefonja vagy táblagépe feloldása nélkül is vezérelhet néhány eszközt.\n\nA Beállításokban bármikor módosíthatja ezt a funkciót."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Szeretne eszközöket vezérelni a lezárási képernyőn?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Telefonja vagy táblagépe feloldása nélkül is vezérelhet néhány eszközt.\n\nAz eszközön lévő alkalmazással határozhatja meg, hogy mely eszközöket kívánja ilyen módon vezérelni."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Most nem"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Igen"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"A PIN-kód betűket vagy szimbólumokat tartalmaz"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Vezérlők hozzáadása"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Vezérlők szerkesztése"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Alkalmazás hozzáadása"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Alkalmazás eltávolítása"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Kimenetek hozzáadása"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Csoport"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 eszköz kiválasztva"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Nem sikerült a közvetítés"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Legalább négy karaktert használjon"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Legfeljebb 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Legalább egy eszköz rendelkezésre áll"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Váltson képernyőt most"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Hajtsa ki a telefont"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Szeretne képernyőt váltani?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"A nagyobb felbontás érdekében használja a hátlapi kamerát."</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"A nagyobb felbontás érdekében fordítsa meg a telefont"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Összehajtható eszköz kihajtása"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Összehajtható eszköz körbeforgatása"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akkumulátor töltöttségi szintje: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Váltás munkaprofilra"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Bezárás"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lezárási képernyő beállításai"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Nem áll rendelkezésre Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera letiltva"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera és mikrofon letiltva"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon letiltva"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritás mód bekapcsolva"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/tiles_states_strings.xml b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
index 0416a5504ae9..157c552b31a6 100644
--- a/packages/SystemUI/res/values-hu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Ki"</item>
<item msgid="5966994759929723339">"Be"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nem áll rendelkezésre"</item>
+ <item msgid="2478289035899842865">"Ki"</item>
+ <item msgid="5137565285664080143">"Be"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 4bd3a65c9ba4..23f0e9d52616 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Հաջորդ փորձի ժամանակ սխալ PIN կոդ մուտքագրելու դեպքում աշխատանքային պրոֆիլը և դրա տվյալները կջնջվեն։"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Հաջորդ փորձի ժամանակ սխալ գաղտնաբառ մուտքագրելու դեպքում աշխատանքային պրոֆիլը և դրա տվյալները կջնջվեն։"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Հպեք մատնահետքի սկաներին"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Մատնահետքի պատկերակ"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Դեմքը չի հաջողվում ճանաչել։ Օգտագործեք մատնահետքը։"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -187,7 +186,7 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"Մարտկոցը <xliff:g id="NUMBER">%d</xliff:g> տոկոս է:"</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Մարտկոցի լիցքը <xliff:g id="PERCENTAGE">%1$d</xliff:g> տոկոս է։ Այն կաշխատի <xliff:g id="TIME">%2$s</xliff:g>։"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Մարտկոցը լիցքավորվում է: Լիցքը <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> տոկոս է:"</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Մարտկոցի լիցքը <xliff:g id="PERCENTAGE">%d</xliff:g> է։ Լիցքավորումը դադարեցվել է՝ մարտկոցը պաշտպանելու համար։"</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Մարտկոցի լիցքը <xliff:g id="PERCENTAGE">%d</xliff:g> տոկոս է։ Լիցքավորումը դադարեցվել է՝ մարտկոցը պաշտպանելու համար։"</string>
<string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Մարտկոցի լիցքը <xliff:g id="PERCENTAGE">%1$d</xliff:g> է։ Այն կաշխատի <xliff:g id="TIME">%2$s</xliff:g>։ Լիցքավորումը դադարեցվել է՝ մարտկոցը պաշտպանելու նպատակով։"</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"Տեսնել բոլոր ծանուցումները"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"Հեռատիպը միացված է:"</string>
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Աշխատանքային պրոֆիլի կողպէկրան"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Փակել"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Պայծառություն"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Գունաշրջում"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Գունաշտկում"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Տառաչափ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Կառավարել օգտատերերին"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Պատրաստ է"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Փակել"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"էկրանի տեսագրում"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Անանուն"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Սպասման ռեժիմ"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Տառաչափ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Փոքրացնել"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Մեծացնել"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Խոշորացման պատուհան"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Խոշորացման պատուհանի կառավարման տարրեր"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Մեծացնել"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Ավելացվեց կառավարման # տարր։}one{Ավելացվեց կառավարման # տարր։}other{Ավելացվեց կառավարման # տարր։}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Հեռացված է"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Ավելացնե՞լ <xliff:g id="APPNAME">%s</xliff:g> հավելվածը"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Եթե ավելացնեք <xliff:g id="APPNAME">%s</xliff:g> հավելվածը, այն կարող է կարգավորումներ և բովանդակություն ավելացնել այս վահանակում։ Որոշ հավելվածներում դուք կարող եք ընտրել, թե որ կարգավորումները ցուցադրվեն այստեղ։"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Հեռացնե՞լ <xliff:g id="APPNAME">%s</xliff:g> հավելվածի համար կարգավորումները։"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Ավելացված է ընտրանիում"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ավելացված է ընտրանիում, դիրքը՝ <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Հեռացված է ընտրանուց"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Այլ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Ավելացրեք սարքերի կառավարման տարրերում"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Ավելացնել"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Հեռացնել"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Առաջարկվել է <xliff:g id="APP">%s</xliff:g> հավելվածի կողմից"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Սարքը կողպված է"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Ցույց տա՞լ և կառավարել սարքերը կողպէկրանից"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Դուք կարող եք կարգավորումներ ավելացնել ձեր արտաքին սարքերի համար կողպէկրանին։\n\nՁեր սարքի հավելվածը կարող է ձեզ թույլ տալ որոշ սարքեր կառավարել առանց ապակողպելու հեռախոսը կամ պլանշետը։\n\nՑանկացած ժամանակ փոփոխություններ կատարեք Կարգավորումներում։"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Կառավարե՞լ սարքերը կողպէկրանից"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Դուք կարող եք կառավարել որոշ սարքեր՝ առանց ապակողպելու ձեր հեռախոսը կամ պլանշետը։\n\nՁեր սարքի հավելվածը որոշում է, թե որ սարքերը կարելի է կառավարել այս եղանակով։"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ոչ, շնորհակալություն"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Այո"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN կոդը տառեր և նշաններ է պարունակում"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Ավելացնել կառավարման տարրեր"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Փոփոխել կառավարման տարրերը"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ավելացնել հավելված"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Հեռացնել հավելվածը"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ավելացրեք մուտքագրման սարքեր"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Խումբ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Ընտրված է 1 սարք"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Հասանելի է առնվազն մեկ սարք"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Հպեք դյուրանցմանը և պահեք"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Չեղարկել"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Փոխել էկրանը հիմա"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Բացեք հեռախոսի փեղկը"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Փոխե՞լ էկրանը"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Ավելի մեծ լուծաչափի համար օգտագործեք հիմնական տեսախցիկը"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Ավելի մեծ լուծաչափի համար շրջեք հեռախոսը"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ծալովի սարք՝ բացված վիճակում"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Ծալովի սարք՝ շրջված վիճակում"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Մարտկոցի լիցքը՝ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Անցնել աշխատանքային պրոֆիլ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Փակել"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Կողպէկրանի կարգավորումներ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ցանց հասանելի չէ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Տեսախցիկն արգելափակված է"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Տեսախցիկն ու խոսափողը արգելափակված են"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Խոսափողն արգելափակված է"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Առաջնահերթության ռեժիմը միացված է"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/tiles_states_strings.xml b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
index 9f30f1cd3a87..089716fa51d6 100644
--- a/packages/SystemUI/res/values-hy/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Անջատված է"</item>
<item msgid="5966994759929723339">"Միացված է"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Հասանելի չէ"</item>
+ <item msgid="2478289035899842865">"Անջատված է"</item>
+ <item msgid="5137565285664080143">"Միացված է"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 0618ec6d6463..1402f3d1e1a1 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jika Anda memasukkan PIN yang salah saat mencoba lagi, profil kerja dan datanya akan dihapus."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Jika Anda memasukkan sandi yang salah saat mencoba lagi, profil kerja dan datanya akan dihapus."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sentuh sensor sidik jari"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikon sidik jari"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tidak dapat mengenali wajah. Gunakan sidik jari."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bayangan pemberitahuan."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Setelan cepat."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Setelan cepat dan Menu notifikasi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Layar kunci."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Layar kunci kantor"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Kecerahan"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversi warna"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Koreksi warna"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Ukuran font"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Kelola pengguna"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Selesai"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Tutup"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"perekaman layar"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Tanpa judul"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Siaga"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Ukuran Font"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Buat lebih kecil"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Buat lebih besar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Jendela Pembesaran"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrol Jendela Pembesaran"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Perbesar"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrol ditambahkan.}other{# kontrol ditambahkan.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Dihapus"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Tambahkan <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Jika Anda menambahkannya, <xliff:g id="APPNAME">%s</xliff:g> dapat menambahkan kontrol dan konten ke panel ini. Di beberapa aplikasi, Anda dapat memilih kontrol yang akan muncul di sini."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Hapus kontrol untuk <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Difavoritkan"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Difavoritkan, posisi <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Batal difavoritkan"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Lainnya"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Tambahkan ke kontrol perangkat"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Tambahkan"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Hapus"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Disarankan oleh <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Perangkat terkunci"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Tampilkan dan kontrol perangkat dari layar kunci?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Anda dapat menambahkan kontrol untuk perangkat eksternal ke layar kunci.\n\nAplikasi perangkat Anda mungkin mengizinkan Anda mengontrol beberapa perangkat tanpa membuka kunci ponsel atau tablet.\n\nAnda dapat melakukan perubahan kapan saja di Setelan."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Kontrol perangkat dari layar kunci?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Anda dapat mengontrol beberapa perangkat eksternal tanpa membuka kunci ponsel atau tablet.\n\nAplikasi perangkat Anda menentukan perangkat yang dapat dikontrol dengan cara ini."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Lain kali"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ya"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN berisi huruf atau simbol"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Tambahkan kontrol"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit kontrol"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tambahkan aplikasi"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Hapus aplikasi"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tambahkan output"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 perangkat dipilih"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Tidak dapat menyiarkan"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gunakan minimal 4 karakter"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gunakan kurang dari 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Tersedia minimal satu perangkat"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Beralih layar sekarang"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Bentangkan ponsel"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Beralih layar?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Untuk resolusi lebih tinggi, gunakan kamera belakang"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Untuk resolusi lebih tinggi, balik ponsel"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Perangkat foldable sedang dibentangkan"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Perangkat foldable sedang dibalik"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Baterai tersisa <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Beralih ke profil kerja"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Tutup"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Setelan layar kunci"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi tidak tersedia"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera diblokir"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dan mikrofon diblokir"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon diblokir"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode prioritas diaktifkan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/tiles_states_strings.xml b/packages/SystemUI/res/values-in/tiles_states_strings.xml
index c31404089220..71460a71b414 100644
--- a/packages/SystemUI/res/values-in/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-in/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Nonaktif"</item>
<item msgid="5966994759929723339">"Aktif"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Tidak tersedia"</item>
+ <item msgid="2478289035899842865">"Nonaktif"</item>
+ <item msgid="5137565285664080143">"Aktif"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index afdaa5dbd56d..3343cf04ad30 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ef þú slærð inn rangt PIN-númer í næstu tilraun verður vinnusniðinu þínu og gögnum þess eytt."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ef þú slærð inn rangt aðgangsorð í næstu tilraun verður vinnusniðinu þínu og gögnum þess eytt."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Snertu fingrafaralesarann"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingrafaratákn"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Andlit þekkist ekki. Notaðu fingrafar í staðinn."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -187,8 +186,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> prósent á rafhlöðu."</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Hleðsla rafhlöðu er <xliff:g id="PERCENTAGE">%1$d</xliff:g> prósent, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Rafhlaða í hleðslu, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Hleðsla rafhlöðu er <xliff:g id="PERCENTAGE">%d</xliff:g> prósent, hlé gert á hleðslu til að vernda rafhlöðuna."</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Hleðsla rafhlöðu er <xliff:g id="PERCENTAGE">%1$d</xliff:g> prósent, <xliff:g id="TIME">%2$s</xliff:g>, hlé gert á hleðslu til að vernda rafhlöðuna."</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Rafhleðsla er <xliff:g id="PERCENTAGE">%d</xliff:g> prósent, hlé gert á hleðslu til að vernda rafhlöðuna."</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Rafhleðsla er <xliff:g id="PERCENTAGE">%1$d</xliff:g> prósent, <xliff:g id="TIME">%2$s</xliff:g>, hlé gert á hleðslu til að vernda rafhlöðuna."</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"Sjá allar tilkynningar"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"Fjarriti virkur."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Titrar við hringingu."</string>
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Tilkynningasvæði."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Flýtistillingar."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Flýtistillingar og tilkynningagluggi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lásskjár."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Vinnulásskjár"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Loka"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Birtustig"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Umsnúningur lita"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Litaleiðrétting"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Leturstærð"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Stjórna notendum"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Lokið"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Loka"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"skjáupptaka"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Enginn titill"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Biðstaða"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Leturstærð"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Minnka"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Stækka"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Stækkunargluggi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Stækkunarstillingar glugga"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Auka aðdrátt"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# stýringu bætt við.}one{# stýringu bætt við.}other{# stýringum bætt við.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Fjarlægt"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Viltu bæta <xliff:g id="APPNAME">%s</xliff:g> við?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Þegar þú bætir <xliff:g id="APPNAME">%s</xliff:g> við getur það bætt stýringum og efni við þetta svæði. Í sumum forritum geturðu valið hvaða stýringar birtast hér."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Fjarlægja stýringar fyrir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Eftirlæti"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Eftirlæti, staða <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjarlægt úr eftirlæti"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Annað"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Bæta við tækjastjórnun"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Bæta við"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Fjarlægja"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Tillaga frá <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Tækið er læst"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Sjá og stjórna tækjum á lásskjánum?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Þú getur bætt við stýringum fyrir ytri tæki á lásskjáinn.\n\nForrit tækisins kann að leyfa þér að stjórna sumum tækjum án þess að taka símann eða spjaldtölvuna úr lás.\n\nÞú getur gert breytingar hvenær sem er í stillingunum."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Stjórna tækjum á lásskjá?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Þú getur stjórnað sumum tækjum án þess að taka símann eða spjaldtölvuna úr lás.\n\nForrit tækisins ákvarðar hvaða tækjum er hægt að stjórna á þennan hátt."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nei, takk"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Já"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN inniheldur bókstafi eða tákn"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Bæta við stýringum"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Breyta stýringum"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Bæta við forriti"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Fjarlægja forrit"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Bæta við úttaki"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Hópur"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 tæki valið"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Ekki hægt að senda út"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Notaðu að minnsta kosti 4 stafi"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Notaðu færri en 16 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>
@@ -1032,16 +1031,11 @@
<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_press_too_short" msgid="8145437175134998864">"Haltu flýtilyklinum inni"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Hætta við"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Skipta um skjá núna"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Opnaðu símann"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Skipta um skjá?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Notaðu aftari myndavélina til að fá betri upplausn"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Snúðu símanum til að fá betri upplausn"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Samanbrjótanlegt tæki opnað"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Samanbrjótanlegu tæki snúið við"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> hleðsla eftir á rafhlöðu"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Skipta yfir í vinnusnið"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Loka"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Stillingar fyrir lásskjá"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ekki til staðar"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Lokað fyrir myndavél"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Lokað fyrir myndavél og hljóðnema"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Lokað fyrir hljóðnema"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Kveikt er á forgangsstillingu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/tiles_states_strings.xml b/packages/SystemUI/res/values-is/tiles_states_strings.xml
index cca4943a062e..17aaf6c2a877 100644
--- a/packages/SystemUI/res/values-is/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-is/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Slökkt"</item>
<item msgid="5966994759929723339">"Kveikt"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ekki tiltækt"</item>
+ <item msgid="2478289035899842865">"Slökkt"</item>
+ <item msgid="5137565285664080143">"Kveikt"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 2f366ecab79c..f38d45d50c23 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Se al prossimo tentativo inserirai un PIN sbagliato, il tuo profilo di lavoro e i relativi dati verranno eliminati."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Se al prossimo tentativo inserirai una password sbagliata, il tuo profilo di lavoro e i relativi dati verranno eliminati."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Tocca il sensore di impronte"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icona dell\'impronta"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Impossibile riconoscere il volto. Usa l\'impronta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Area notifiche."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Impostazioni rapide."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Area notifiche e Impostazioni rapide."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Schermata di blocco."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Schermata di blocco del profilo di lavoro"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Chiudi"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminosità"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversione dei colori"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correzione del colore"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Dimensioni carattere"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gestisci utenti"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Fine"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Chiudi"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Avvia adesso"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Nessuna notifica"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nessuna nuova notifica"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Sblocca per notifiche meno recenti"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Sblocca per vedere le notifiche meno recenti"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Questo dispositivo è gestito dai tuoi genitori"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Questo dispositivo appartiene alla tua organizzazione, che potrebbe monitorare il traffico di rete"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Questo dispositivo appartiene a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, che potrebbe monitorare il traffico di rete"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"Registraz. schermo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Senza titolo"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Dimensioni carattere"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Rimpicciolisci"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Ingrandisci"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Finestra ingrandimento"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Finestra controlli di ingrandimento"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumenta lo zoom"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controllo aggiunto.}many{# controlli aggiunti.}other{# controlli aggiunti.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Rimosso"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Vuoi aggiungere <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Se la aggiungi, l\'app <xliff:g id="APPNAME">%s</xliff:g> può aggiungere controlli e contenuti a questo riquadro. In alcune app puoi scegliere quali controlli visualizzare qui."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vuoi rimuovere i controlli per l\'app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Aggiunto ai preferiti"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Preferito, posizione <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Rimosso dai preferiti"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Altro"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Aggiungi al controllo dei dispositivi"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Aggiungi"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Rimuovi"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Suggerito da <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloccato"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vuoi visualizzare e controllare i dispositivi dalla schermata di blocco?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Puoi aggiungere impostazioni alla schermata di blocco per i tuoi dispositivi esterni.\n\nL\'app del tuo dispositivo potrebbe consentirti di controllare alcuni dispositivi senza dover sbloccare il tuo telefono o tablet.\n\nPuoi apportare modifiche in qualsiasi momento in Impostazioni."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vuoi controllare i dispositivi dalla schermata di blocco?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Puoi controllare alcuni dispositivi senza dover sbloccare il tuo telefono o tablet.\n\nL\'app del tuo dispositivo determina quali dispositivi possono essere controllati in questo modo."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, grazie"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sì"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Il PIN contiene lettere o simboli"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Aggiungi controlli"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Modifica controlli"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Aggiungi app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Rimuovi l\'app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Aggiungi uscite"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selezionato"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Impossibile trasmettere"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa almeno 4 caratteri"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa meno di 16 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>
@@ -962,7 +961,7 @@
<string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonata in corso"</string>
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Dati mobili"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
- <string name="mobile_data_connection_active" msgid="944490013299018227">"Connessione attiva"</string>
+ <string name="mobile_data_connection_active" msgid="944490013299018227">"Connessa"</string>
<string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connessa temporaneamente"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Connessione debole"</string>
<string name="mobile_data_off_summary" msgid="3663995422004150567">"Nessuna connessione dati mobili automatica"</string>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ci sia almeno un dispositivo disponibile"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Cambia schermo ora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Apri il telefono"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vuoi cambiare schermo?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Usa la fotocamera posteriore per una maggiore risoluzione"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Gira il telefono per una maggiore risoluzione"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo pieghevole che viene aperto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo pieghevole che viene capovolto"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batteria rimanente"</string>
@@ -1050,7 +1044,12 @@
<string name="video_camera" msgid="7654002575156149298">"Videocamera"</string>
<string name="call_from_work_profile_title" msgid="6991157106804289643">"Impossibile chiamare da questo profilo"</string>
<string name="call_from_work_profile_text" msgid="3458704745640229638">"Le norme di lavoro ti consentono di fare telefonate soltanto dal profilo di lavoro"</string>
- <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passa a profilo di lavoro"</string>
+ <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passa al profilo di lavoro"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Chiudi"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Impostazioni schermata di blocco"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponibile"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Videocamera bloccata"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Videocamera e microfono bloccati"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfono bloccato"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modalità priorità attivata"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/tiles_states_strings.xml b/packages/SystemUI/res/values-it/tiles_states_strings.xml
index 79e5aca07162..7aa09d420f87 100644
--- a/packages/SystemUI/res/values-it/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-it/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Off"</item>
<item msgid="5966994759929723339">"On"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Non disponibile"</item>
+ <item msgid="2478289035899842865">"Off"</item>
+ <item msgid="5137565285664080143">"On"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 840744bb9afb..e10415507939 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"הזנה של קוד אימות שגוי בניסיון הבא תגרום למחיקת פרופיל העבודה והנתונים המשויכים אליו."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"הזנת סיסמה שגויה בניסיון הבא תגרום למחיקת פרופיל העבודה והנתונים המשויכים אליו."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"יש לגעת בחיישן טביעות האצבע"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"סמל טביעת אצבע"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"לא ניתן לזהות את הפנים. יש להשתמש בטביעת אצבע במקום."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"מסך נעילה של עבודה"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"סגירה"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"בהירות"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"היפוך צבעים"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"תיקון צבע"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"גודל הגופן"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ניהול משתמשים"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"סיום"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"סגירה"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"הקלטת המסך"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ללא שם"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"המתנה"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"גודל גופן"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"הקטנה"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"הגדלה"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"חלון הגדלה"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"בקרות של חלון ההגדלה"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"התקרבות"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{נוסף אמצעי בקרה אחד (#).}one{נוספו # אמצעי בקרה.}two{נוספו # אמצעי בקרה.}other{נוספו # אמצעי בקרה.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"הוסר"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"להוסיף את <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"כשמוסיפים את האפליקציה <xliff:g id="APPNAME">%s</xliff:g>, היא תוכל להוסיף אמצעי בקרה ותוכן לחלונית הזו. חלק מהאפליקציות מאפשרות לבחור אילו אמצעי בקרה יוצגו כאן."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"להסיר את אמצעי הבקרה של <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"סומן כמועדף"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"סומן כמועדף, במיקום <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"הוסר מהמועדפים"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"אחר"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"הוספה לפקדי המכשירים"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"הוספה"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"הסרה"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"הוצע על-ידי <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"המכשיר נעול"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"להציג מכשירים ולאפשר שליטה בהם במסך הנעילה?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ניתן להוסיף למסך הנעילה אמצעי בקרה למכשירים החיצוניים.\n\nיכול להיות שהאפליקציה של המכשיר תאפשר לך לשלוט בחלק מהמכשירים בלי לבטל את הנעילה של הטלפון או הטאבלט.\n\nאפשר לבצע שינויים בכל שלב בהגדרות."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"לאפשר שליטה במכשירים במסך הנעילה?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"אפשר לשלוט בחלק מהמכשירים בלי לבטל את הנעילה של הטלפון או הטאבלט.\n\nהמכשירים שניתן לשלוט בהם באופן הזה נקבעים באפליקציה של המכשיר."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"לא תודה"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"כן"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"קוד האימות מכיל אותיות או סמלים"</string>
@@ -876,12 +876,13 @@
<string name="controls_error_removed" msgid="6675638069846014366">"לא נמצא"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"הפקד לא זמין"</string>
<string name="controls_error_removed_message" msgid="2885911717034750542">"לא ניתן להתחבר אל <xliff:g id="DEVICE">%1$s</xliff:g>. יש לבדוק את האפליקציה <xliff:g id="APPLICATION">%2$s</xliff:g> כדי לוודא שהפקד עדיין זמין ושהגדרות האפליקציה לא השתנו."</string>
- <string name="controls_open_app" msgid="483650971094300141">"לפתיחת האפליקציה"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"פתיחת האפליקציה"</string>
<string name="controls_error_generic" msgid="352500456918362905">"לא ניתן לטעון את הסטטוס"</string>
<string name="controls_error_failed" msgid="960228639198558525">"שגיאה, יש לנסות שוב"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"הוספת פקדים"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"עריכת פקדים"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"הוספת אפליקציה"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"הסרת האפליקציה"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"הוספת מכשירי פלט"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"קבוצה"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"נבחר מכשיר אחד"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• יש לפחות מכשיר אחד זמין"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"מקש קיצור ללחיצה ארוכה"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ביטול"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"כן, אני רוצה להחליף בין המסכים"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"פתיחת הטלפון"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"להחליף בין המסכים?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"כדי לצלם תמונה ברזולוציה גבוהה יותר, כדאי להשתמש במצלמה האחורית"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"כדי לצלם תמונה ברזולוציה גבוהה יותר, כדאי להפוך את הטלפון"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"מכשיר מתקפל עובר למצב לא מקופל"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"מכשיר מתקפל עובר למצב מהופך"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"רמת הטעינה שנותרה בסוללה: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"מעבר לפרופיל עבודה"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"סגירה"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"הגדרות מסך הנעילה"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏ה-Wi-Fi לא זמין"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"המצלמה חסומה"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"המצלמה והמיקרופון חסומים"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"המיקרופון חסום"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"מצב \'עדיפות\' מופעל"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/tiles_states_strings.xml b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
index 374f5af7f513..d5a0e7236f55 100644
--- a/packages/SystemUI/res/values-iw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"כבוי"</item>
<item msgid="5966994759929723339">"מופעל"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"לא זמין"</item>
+ <item msgid="2478289035899842865">"מושבת"</item>
+ <item msgid="5137565285664080143">"מופעל"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 4e9c1bdda389..2b8f14768d66 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"PIN をあと 1 回間違えると、仕事用プロファイルと関連データが削除されます。"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"パスワードをあと 1 回間違えると、仕事用プロファイルと関連データが削除されます。"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"指紋認証センサーをタッチ"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"指紋アイコン"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"顔を認識できません。指紋認証を使用してください。"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"仕事用プロファイルのロック画面"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"閉じる"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"画面の明るさ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"色反転"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色補正"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"フォントサイズ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ユーザーを管理"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"完了"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"閉じる"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"画面の録画"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"タイトルなし"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"スタンバイ"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"フォントサイズ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"縮小"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"拡大"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"拡大ウィンドウ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"拡大ウィンドウ コントロール"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"拡大"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# 件のコントロールを追加しました。}other{# 件のコントロールを追加しました。}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"削除済み"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> を追加しますか?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> を追加することで、コントロールやコンテンツをこのパネルに追加できます。一部のアプリでは、ここに表示されるコントロールを選択できます。"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> のコントロールを削除しますか?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"お気に入りに追加済み"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"お気に入りに追加済み、位置: <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"お気に入りから削除済み"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"その他"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"デバイス コントロールに追加"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"追加"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"削除"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> によるおすすめ"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"デバイス: ロック状態"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ロック画面にデバイスを表示して操作しますか?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ロック画面に外部デバイスのコントロールを追加できます。\n\nスマートフォンやタブレットのロックを解除しなくても、デバイスアプリによって一部のデバイスを操作できる可能性があります。\n\n設定でいつでも変更できます。"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ロック画面でデバイスを操作しますか?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"スマートフォンやタブレットのロックを解除しなくても一部のデバイスを操作できます。\n\nこの方法でどのデバイスを操作できるかは、デバイスアプリが判断します。"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"いいえ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"はい"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN に英字や記号を含める"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"コントロールを追加"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"コントロールを編集"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"アプリを追加"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"アプリを削除"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"出力の追加"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"グループ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"選択したデバイス: 1 台"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• 利用できるデバイスが 1 台以上ある"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ショートカットの長押しが必要です"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"キャンセル"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"画面を切り替えましょう"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"スマートフォンを開いてください"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"画面を切り替えますか?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"高解像度で撮るには背面カメラを使用してください"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"高解像度で撮るにはスマートフォンを裏返してください"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"折りたたみ式デバイスが広げられている"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"折りたたみ式デバイスがひっくり返されている"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"バッテリー残量 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"仕事用プロファイルに切り替える"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"閉じる"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ロック画面の設定"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi は利用できません"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"カメラはブロックされています"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"カメラとマイクはブロックされています"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"マイクはブロックされています"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"優先モードは ON です"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/tiles_states_strings.xml b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
index 64f7c394499c..31158ca59882 100644
--- a/packages/SystemUI/res/values-ja/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"OFF"</item>
<item msgid="5966994759929723339">"ON"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"使用不可"</item>
+ <item msgid="2478289035899842865">"OFF"</item>
+ <item msgid="5137565285664080143">"ON"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index b6ab02c554a4..956bd853c05a 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"შემდეგი მცდელობისას PIN-კოდის არასწორად შეყვანის შემთხვევაში, თქვენი სამსახურის პროფილი და მისი მონაცემები წაიშლება."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"შემდეგი მცდელობისას პაროლის არასწორად შეყვანის შემთხვევაში, თქვენი სამსახურის პროფილი და მისი მონაცემები წაიშლება."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"შეეხეთ თითის ანაბეჭდის სენსორს"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"თითის ანაბეჭდის ხატულა"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"სახის ამოცნობა ვერ ხერხდება. სანაცვლოდ თითის ანაბეჭდი გამოიყენეთ."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"სამსახურის ჩაკეტილი ეკრანი"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"დახურვა"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"განათება"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ფერთა ინვერსია"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ფერთა კორექცია"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"შრიფტის ზომა"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"მომხმარებლების მართვა"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"დასრულდა"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"დახურვა"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ეკრანის ჩაწერა"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"უსათაურო"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"მოლოდინის რეჟიმი"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"შრიფტის ზომა"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"დაპატარავება"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"გადიდება"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"გადიდების ფანჯარა"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"გადიდების კონტროლის ფანჯარა"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"მასშტაბის გადიდება"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{დაემატა მართვის # საშუალება.}other{დაემატა მართვის # საშუალება.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"ამოიშალა"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"გსურთ <xliff:g id="APPNAME">%s</xliff:g>-ის დამატება?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"როდესაც <xliff:g id="APPNAME">%s</xliff:g>-ს ამატებთ, მან შეიძლება დაამატოს მართვის საშუალებები და კონტენტი მოცემულ არეში. ზოგიერთ აპში შეგიძლიათ აირჩიოთ, რომელი მართვის საშუალებები უნდა გამოჩნდეს აქ."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"ამოიშალოს <xliff:g id="APPNAME">%s</xliff:g>-ის მართვის საშუალებები?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"რჩეულებშია"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"რჩეულებშია, პოზიციაზე <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"რჩეულებიდან ამოღებულია"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"სხვა"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"მოწყობილ. მართვის საშუალებებში დამატება"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"დამატება"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"ამოშლა"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"შემოთავაზებულია <xliff:g id="APP">%s</xliff:g>-ის მიერ"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"მოწყობილ. ჩაკეტილია"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"გსურთ მოწყობილობების ჩვენება და მართვა ჩაკეტილი ეკრანიდან?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"შეგიძლიათ დაამატოთ მართვის საშუალებები გარე მოწყობილობებისთვის, ჩაკეტილ ეკრანზე.\n\nთქვენი მოწყობილობის აპმა შეიძლება მოგცეთ საშუალება, მართოთ ზოგიერთი მოწყობილობა თქვენი ტელეფონის ან ტაბლეტის განბლოკვის გარეშე.\n\nცვლილებების შეტანა ნებისმიერ დროს შეგიძლიათ პარამეტრებიდან."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"გსურთ მოწყობილობების მართვა ჩაკეტილი ეკრანიდან?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"შეგიძლიათ ზოგიერთი მოწყობილობის მართვა ტელეფონის ან ტაბლეტის განბლოკვის გარეშე.\n\nთქვენი მოწყობილობის აპი განსაზღვრავს, რომელი მოწყობილობა იმართება ამგვარად."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"არა, გმადლობთ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"დიახ"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-კოდი შეიცავს ასოებს ან სიმბოლოებს"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"მართვის საშუალებების დამატება"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"მართვის საშუალებათა რედაქტირება"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"აპის დამატება"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"აპის ამოშლა"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"მედია-გამოსავლების დამატება"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"ჯგუფი"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"არჩეულია 1 მოწყობილობა"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ხელმისაწვდომია მინიმუმ ერთი მოწყობილობა"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"შეხების დაamp; მოცდის მალსახმობი"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"გაუქმება"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ეკრანების ახლა გადართვა"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"გაშალეთ ტელეფონი"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"გადაირთოს ეკრანები?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"მაღალი გარჩევადობისთვის გამოიყენეთ უკანა კამერა"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"მაღალი გარჩევადობისთვის ამოაბრუნეთ ტელეფონი"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"დასაკეცი მოწყობილობა იხსნება"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"დასაკეცი მოწყობილობა ტრიალებს"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"დარჩენილია ბატარეის <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"სამსახურის პროფილზე გადართვა"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"დახურვა"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ჩაკეტილი ეკრანის პარამეტრები"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi მიუწვდომელია"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"კამერა დაბლოკილია"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"კამერა და მიკროფონი დაბლოკილია"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"მიკროფონი დაბლოკილია"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"პრიორიტეტული რეჟიმი ჩართულია"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/tiles_states_strings.xml b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
index 99c5263a1102..366030a2231f 100644
--- a/packages/SystemUI/res/values-ka/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"გამორთულია"</item>
<item msgid="5966994759929723339">"ჩართულია"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"მიუწვდომელია"</item>
+ <item msgid="2478289035899842865">"გამორთული"</item>
+ <item msgid="5137565285664080143">"ჩართული"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 79d54c55bfb8..aaf7b3245099 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Келесі әрекет кезінде қате PIN кодын енгізсеңіз, жұмыс профиліңіз бен оның деректері жойылады."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Келесі әрекет кезінде қате құпия сөз енгізсеңіз, жұмыс профиліңіз бен оның деректері жойылады."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Саусақ ізін оқу сканерін түртіңіз"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Саусақ ізі белгішесі"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Бет танылмады. Орнына саусақ ізін пайдаланыңыз."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Әрекетті құлыптау экраны"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Жабу"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Жарықтығы"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Түс инверсиясы"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Түсті түзету"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Қаріп өлшемі"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Пайдаланушыларды басқару"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Дайын"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Жабу"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"экранды бейнеге жазу"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Атауы жоқ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Күту режимі"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Қаріп өлшемі"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Кішірейту"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Үлкейту"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ұлғайту терезесі"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ұлғайту терезесінің басқару элементтері"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Ұлғайту"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# басқару элементі қосылды.}other{# басқару элементі қосылды.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Өшірілді"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> қолданбасын қосу керек пе?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> қолданбасын қосқан кезде, басқару элементтері мен контент осы панельге енгізіледі. Кейбір қолданбада басқару элементтерінің қайсысы осы жерде көрсетілетінін таңдай аласыз."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> қолданбасының басқару элементтері жойылсын ба?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Таңдаулыларға қосылды"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Таңдаулыларға қосылды, <xliff:g id="NUMBER">%d</xliff:g>-позиция"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Таңдаулылардан алып тасталды"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Басқа"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Құрылғы басқару элементтеріне қосу"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Енгізу"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Өшіру"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ұсынған"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Құрылғы құлыпталды."</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Құрылғыларды құлып экранынан көрсетуге және басқаруға рұқсат берілсін бе?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Сыртқы құрылғылардың басқару элементтерін құлып экранына қоса аласыз.\n\nҚұрылғы қолданбасы кейбір құрылғыларды телефонның немесе планшеттің құлпын ашпастан басқаруға мүмкіндік береді.\n\n\"Параметрлер\" бөлімінде кез келген уақытта өзгерістер енгізуге болады."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Құрылғылар құлып экранынан басқарылсын ба?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Кейбір құрылғыларды телефонның немесе планшеттің құлпын ашпастан басқара аласыз.\n\nҚұрылғы қолданбасы осылай басқаруға болатын құрылғыларды анықтайды."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Жоқ, рақмет"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Иә"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN коды әріптерден не таңбалардан құралады."</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Басқару элементтерін қосу"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Басқару элементтерін өзгерту"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Қолданба қосу"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Қолданбаны өшіру"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Шығыс сигналдарды қосу"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Топ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 құрылғы таңдалды."</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Тарату мүмкін емес"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Сақталмайды. Қайталап көріңіз."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Сақталмайды."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Кемінде 4 таңба пайдаланыңыз."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Ең көбі 16 таңба пайдаланыңыз."</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Кемінде бір құрылғы қолжетімді"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Таңбашаны басып тұрыңыз."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Бас тарту"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Экрандарды қазір ауыстыру"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Телефонды ашу"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Экрандарды ауыстыру керек пе?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Жоғары ажыратымдылық үшін артқы камераны пайдаланыңыз."</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Жоғары ажыратымдылық үшін телефонды айналдырыңыз."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Бүктемелі құрылғы ашылып жатыр."</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Бүктемелі құрылғы аударылып жатыр."</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Қалған батарея заряды: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Жұмыс профиліне ауысу"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Жабу"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Экран құлпының параметрлері"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi қолжетімсіз."</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера бөгелген."</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера мен микрофон бөгелген."</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон бөгелген."</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\"Маңызды\" режимі қосулы."</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/tiles_states_strings.xml b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
index be7546eb7686..b8089e44a5ce 100644
--- a/packages/SystemUI/res/values-kk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Өшірулі."</item>
<item msgid="5966994759929723339">"Қосулы."</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Қолжетімсіз"</item>
+ <item msgid="2478289035899842865">"Өшірулі"</item>
+ <item msgid="5137565285664080143">"Қосулы"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 306d104a9292..2f3e2f4f4def 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ប្រសិនបើអ្នក​បញ្ចូលកូដ PIN មិនត្រឹមត្រូវ នៅពេលព្យាយាមបញ្ចូល​លើកក្រោយ កម្រងព័ត៌មានការងាររបស់អ្នក និងទិន្នន័យរបស់កម្រងព័ត៌មាននេះ​នឹងត្រូវបានលុប។"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ប្រសិនបើអ្នក​បញ្ចូលពាក្យសម្ងាត់មិន​ត្រឹមត្រូវ នៅពេលព្យាយាមបញ្ចូល​លើកក្រោយ កម្រងព័ត៌មាន​ការងាររបស់អ្នក និងទិន្នន័យ​របស់កម្រងព័ត៌មាននេះនឹងត្រូវបានលុប។"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ប៉ះ​ឧបករណ៍​ចាប់ស្នាម​ម្រាមដៃ"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"រូប​ស្នាម​ម្រាមដៃ"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"មិនអាចសម្គាល់មុខបានទេ។ សូមប្រើស្នាមម្រាមដៃជំនួសវិញ។"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"អេក្រង់​ចាក់​សោ​លក្ខណៈ​ការងារ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"បិទ"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ពន្លឺ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ការបញ្ច្រាស​ពណ៌"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ការ​កែតម្រូវ​ពណ៌"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ទំហំ​ពុម្ព​អក្សរ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"គ្រប់គ្រង​អ្នក​ប្រើប្រាស់"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"រួចរាល់"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"បិទ"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ការថតវីដេអូអេក្រង់"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"គ្មាន​ចំណងជើង"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ផ្អាក​ដំណើរការ"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ទំហំពុម្ពអក្សរ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"កំណត់ឱ្យតូចជាងមុន"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"កំណត់ឱ្យធំជាងមុន"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"វិនដូ​ការពង្រីក"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"វិនដូគ្រប់គ្រង​​ការពង្រីក"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ពង្រីក"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{បានបញ្ចូល​ការគ្រប់គ្រង #។}other{បានបញ្ចូល​ការគ្រប់គ្រង #។}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"បានដកចេញ"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"បញ្ចូល <xliff:g id="APPNAME">%s</xliff:g> ឬ?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"នៅពេលអ្នកបញ្ចូល <xliff:g id="APPNAME">%s</xliff:g> កម្មវិធីនេះអាចបញ្ចូលការគ្រប់គ្រង និងខ្លឹមសារទៅផ្ទាំងនេះបាន។ ក្នុងកម្មវិធីមួយចំនួន អ្នកអាចជ្រើសរើសឱ្យការគ្រប់គ្រងណាខ្លះបង្ហាញនៅទីនេះបាន។"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"ដកការគ្រប់គ្រងសម្រាប់ <xliff:g id="APPNAME">%s</xliff:g> ចេញឬ?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"បានដាក់ជា​សំណព្វ"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"បានដាក់ជា​សំណព្វ ទីតាំង​ទី <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"បានដកចេញ​ពី​សំណព្វ"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ផ្សេងៗ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"បញ្ចូល​ទៅក្នុងផ្ទាំងគ្រប់គ្រងឧបករណ៍"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"បញ្ចូល"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"ដកចេញ"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"បាន​ណែនាំដោយ <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"បានចាក់សោ​ឧបករណ៍"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"បង្ហាញ និង​គ្រប់គ្រង​ឧបករណ៍ពី​អេក្រង់ចាក់សោឬ?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"អ្នកអាចបញ្ចូល​ការគ្រប់គ្រង​សម្រាប់ឧបករណ៍​ខាងក្រៅ​របស់អ្នក​ទៅក្នុងអេក្រង់​ចាក់សោបាន។\n\nកម្មវិធី​ឧបករណ៍​របស់អ្នក​អាចអនុញ្ញាតឱ្យអ្នក​គ្រប់គ្រង​ឧបករណ៍​មួយចំនួន ដោយមិនចាំបាច់​ដោះសោ​ទូរសព្ទ ឬ​ថេប្លេត​របស់អ្នក។\n\nអ្នកអាចធ្វើការផ្លាស់ប្ដូរ​បានគ្រប់ពេល​នៅក្នុង​ការកំណត់។"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"គ្រប់គ្រង​ឧបករណ៍ពី​អេក្រង់ចាក់សោឬ?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"អ្នកអាចគ្រប់គ្រង​ឧបករណ៍​មួយចំនួន ដោយមិនចាំបាច់​ដោះសោ​ទូរសព្ទ ឬថេប្លេត​របស់អ្នក។\n\nកម្មវិធី​ឧបករណ៍​របស់អ្នក​កំណត់ឧបករណ៍​ដែលអាចត្រូវបានគ្រប់គ្រង​តាមវិធីនេះ។"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ទេ អរគុណ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"បាទ/ចាស"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"កូដ PIN មាន​អក្សរ ឬនិមិត្តសញ្ញា"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"បញ្ចូល​ផ្ទាំងគ្រប់គ្រង"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"កែ​ផ្ទាំងគ្រប់គ្រង"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"បញ្ចូល​កម្មវិធី"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"ដក​កម្មវិធី​ចេញ"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"បញ្ចូល​ឧបករណ៍​មេឌៀ"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"ក្រុម"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"បានជ្រើសរើស​ឧបករណ៍ 1"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"មិនអាចផ្សាយបានទេ"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"មិនអាច​រក្សាទុក​បានទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"មិនអាច​រក្សាទុក​បានទេ។"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ប្រើយ៉ាងហោចណាស់ 4 តួអក្សរ"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ប្រើតិចជាង 16 តួអក្សរ"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ឧបករណ៍យ៉ាងតិចមួយអាចប្រើបាន"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ចុចឱ្យជាប់លើផ្លូវកាត់"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"បោះបង់"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ប្ដូរអេក្រង់ឥឡូវនេះ"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"លាតទូរសព្ទ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ប្ដូរអេក្រង់ឬ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"សម្រាប់កម្រិតគុណភាពកាន់តែខ្ពស់ សូមប្រើប្រាស់កាមេរ៉ាខាងក្រោយ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"សម្រាប់កម្រិតគុណភាពកាន់តែខ្ពស់ សូមត្រឡប់ទូរសព្ទ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ឧបករណ៍អាច​បត់បានកំពុងត្រូវបានលា"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ឧបករណ៍អាច​បត់បានកំពុងត្រូវបានលា"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"ថ្មនៅសល់ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ប្ដូរ​ទៅ​កម្រង​ព័ត៌មាន​ការងារ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"បិទ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ការកំណត់​អេក្រង់ចាក់សោ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"មិនមាន Wi-Fi ទេ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"បាន​ទប់ស្កាត់​កាមេរ៉ា"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"បានទប់ស្កាត់​កាមេរ៉ា និង​មីក្រូហ្វូន"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"បាន​ទប់ស្កាត់​មីក្រូហ្វូន"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"មុខងារ​អាទិភាពត្រូវបានបើក"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/tiles_states_strings.xml b/packages/SystemUI/res/values-km/tiles_states_strings.xml
index 37e839f01dfc..8c5c8d1ce088 100644
--- a/packages/SystemUI/res/values-km/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-km/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"បិទ"</item>
<item msgid="5966994759929723339">"បើក"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"មិនមានទេ"</item>
+ <item msgid="2478289035899842865">"បិទ"</item>
+ <item msgid="5137565285664080143">"បើក"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 1b186149ed09..c364fb1bf155 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪಿನ್ ನಮೂದಿಸಿದರೆ, ನಿಮ್ಮ ಉದ್ಯೋಗದ ಪ್ರೊಫೈಲ್ ಮತ್ತು ಅದರ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿದರೆ, ನಿಮ್ಮ ಉದ್ಯೋಗದ ಪ್ರೊಫೈಲ್ ಮತ್ತು ಅದರ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌‌ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಐಕಾನ್"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ಮುಖ ಗುರುತಿಸಲಾಗುತ್ತಿಲ್ಲ ಬದಲಿಗೆ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬಳಸಿ."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"ಕೆಲಸದ ಲಾಕ್ ಪರದೆ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ಮುಚ್ಚು"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ಪ್ರಕಾಶಮಾನ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ಕಲರ್ ಇನ್‍ವರ್ಶನ್"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ಫಾಂಟ್ ಗಾತ್ರ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಹಿಸಿ"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ಮುಗಿದಿದೆ"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ಮುಚ್ಚಿರಿ"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ಯಾವುದೇ ಶೀರ್ಷಿಕೆಯಿಲ್ಲ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ಸ್ಟ್ಯಾಂಡ್‌ಬೈ"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ಫಾಂಟ್ ಗಾತ್ರ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ಚಿಕ್ಕದಾಗಿಸಿ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ದೊಡ್ಡದಾಗಿಸಿ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ವರ್ಧನೆಯ ವಿಂಡೋ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ವರ್ಧನೆಯ ವಿಂಡೋ ನಿಯಂತ್ರಣಗಳು"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ಝೂಮ್ ಇನ್ ಮಾಡಿ"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ನಿಯಂತ್ರಣವನ್ನು ಸೇರಿಸಲಾಗಿದೆ.}one{# ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ.}other{# ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ಅನ್ನು ಸೇರಿಸಬೇಕೆ?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"ನೀವು <xliff:g id="APPNAME">%s</xliff:g> ಅನ್ನು ಸೇರಿಸಿದಾಗ, ಅದು ಈ ಪ್ಯಾನೆಲ್‌ಗೆ ನಿಯಂತ್ರಣಗಳು ಮತ್ತು ವಿಷಯವನ್ನು ಸೇರಿಸಬಹುದು. ಕೆಲವು ಆ್ಯಪ್‌ಗಳಲ್ಲಿ, ಇಲ್ಲಿ ಯಾವ ನಿಯಂತ್ರಣಗಳು ಕಾಣಿಸಬೇಕು ಎಂಬುದನ್ನು ನೀವು ಆಯ್ಕೆಮಾಡಬಹುದು."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> ಗಾಗಿ ನಿಯಂತ್ರಣಗಳನ್ನು ತೆಗೆದುಹಾಕಬೇಕೆ?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"ಮೆಚ್ಚಲಾಗಿರುವುದು"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"ಮೆಚ್ಚಲಾಗಿರುವುದು, ಸ್ಥಾನ <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ಮೆಚ್ಚಿನದಲ್ಲದ್ದು"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ಇತರ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ಸಾಧನ ನಿಯಂತ್ರಣಗಳಿಗೆ ಸೇರಿಸಿ"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ಸೇರಿಸಿ"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"ತೆಗೆದುಹಾಕಿ"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ಆ್ಯಪ್ ಸೂಚಿಸಿದೆ"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"ಸಾಧನ ಲಾಕ್ ಆಗಿದೆ"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಿಂದ ಸಾಧನಗಳನ್ನು ತೋರಿಸಬೇಕೇ ಹಾಗೂ ನಿಯಂತ್ರಿಸಬೇಕೇ?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ನಿಮ್ಮ ಬಾಹ್ಯ ಸಾಧನಗಳಿಗಾಗಿ ನೀವು ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಬಹುದು.\n\nನಿಮ್ಮ ಫೋನ್ ಅಥವಾ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡದೆಯೇ ನಿಮ್ಮ ಕೆಲವು ಸಾಧನಗಳನ್ನು ನಿಯಂತ್ರಿಸಲು ನಿಮ್ಮ ಸಾಧನ ಆ್ಯಪ್ ಅನುಮತಿಸಬಹುದು.\n\nಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ನೀವು ಯಾವಾಗ ಬೇಕಾದರೂ ಬದಲಾವಣೆಗಳನ್ನು ಮಾಡಬಹುದು."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಿಂದ ಸಾಧನಗಳನ್ನು ನಿಯಂತ್ರಿಸಬೇಕೇ?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"ನಿಮ್ಮ ಫೋನ್ ಅಥವಾ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡದೆಯೇ ನಿಮ್ಮ ಕೆಲವು ಸಾಧನಗಳನ್ನು ನೀವು ನಿಯಂತ್ರಿಸಬಹುದು.\n\nಈ ವಿಧಾನದ ಮೂಲಕ ಯಾವ ಸಾಧನಗಳನ್ನು ನಿಯಂತ್ರಿಸಬಹುದು ಎಂಬುದನ್ನು ನಿಮ್ಮ ಸಾಧನದ ಆ್ಯಪ್ ನಿರ್ಧರಿಸುತ್ತದೆ."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ಬೇಡ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ಹೌದು"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ಪಿನ್ ಅಕ್ಷರಗಳು ಅಥವಾ ಸಂಕೇತಗಳನ್ನು ಒಳಗೊಂಡಿದೆ"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಿ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ನಿಯಂತ್ರಣಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"ಆ್ಯಪ್ ಅನ್ನು ಸೇರಿಸಿ"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"ಆ್ಯಪ್ ತೆಗೆದುಹಾಕಿ"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"ಔಟ್‌ಪುಟ್‌ಗಳನ್ನು ಸೇರಿಸಿ"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"ಗುಂಪು"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ಸಾಧನವನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ಕನಿಷ್ಠ ಒಂದು ಸಾಧನ ಲಭ್ಯವಿದೆ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ಸ್ಪರ್ಶಿಸಿ ಹೋಲ್ಡ್ ಮಾಡಿ ಶಾರ್ಟ್‌ಕಟ್"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ರದ್ದುಗೊಳಿಸಿ"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ಈಗ ಸ್ಕ್ರೀನ್‌ಗಳನ್ನು ಬದಲಿಸಿ"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಫೋಲ್ಡ್ ಮಾಡಿ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ಸ್ಕ್ರೀನ್‌ಗಳನ್ನು ಬದಲಿಸಬೇಕೆ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ಅಧಿಕ ರೆಸಲ್ಯೂಷನ್‌ಗಾಗಿ, ಹಿಂಬದಿಯ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸಿ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ಅಧಿಕ ರೆಸಲ್ಯೂಷನ್‌ಗಾಗಿ, ಫೋನ್ ಅನ್ನು ಫ್ಲಿಪ್ ಮಾಡಿ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ಫೋಲ್ಡ್ ಮಾಡಬಹುದಾದ ಸಾಧನವನ್ನು ಅನ್‌ಫೋಲ್ಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ಫೋಲ್ಡ್ ಮಾಡಬಹುದಾದ ಸಾಧನವನ್ನು ಸುತ್ತಲೂ ತಿರುಗಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಬ್ಯಾಟರಿ ಉಳಿದಿದೆ"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ಗೆ ಬದಲಿಸಿ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ಮುಚ್ಚಿರಿ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ವೈ-ಫೈ ಲಭ್ಯವಿಲ್ಲ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ಕ್ಯಾಮರಾವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೊಫೋನ್‌ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ಆದ್ಯತೆಯ ಮೋಡ್‌ ಆನ್‌ ಆಗಿದೆ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/tiles_states_strings.xml b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
index 8a2ad2a8bb13..16e82eacdd63 100644
--- a/packages/SystemUI/res/values-kn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"ಆಫ್ ಮಾಡಿ"</item>
<item msgid="5966994759929723339">"ಆನ್ ಮಾಡಿ"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ಲಭ್ಯವಿಲ್ಲ"</item>
+ <item msgid="2478289035899842865">"ಆಫ್ ಆಗಿದೆ"</item>
+ <item msgid="5137565285664080143">"ಆನ್ ಆಗಿದೆ"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 12cef5509c94..8c7d0c5b29c8 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"다음번 시도에서 잘못된 PIN을 입력하면 직장 프로필 및 관련 데이터가 삭제됩니다."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"다음번 시도에서 잘못된 비밀번호를 입력하면 직장 프로필 및 관련 데이터가 삭제됩니다."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"지문 센서를 터치하세요."</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"지문 아이콘"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"얼굴을 인식할 수 없습니다. 대신 지문을 사용하세요."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"업무용 잠금 화면"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"닫기"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"밝기"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"색상 반전"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"색상 보정"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"글꼴 크기"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"사용자 관리"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"완료"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"닫기"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"화면 녹화"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"제목 없음"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"대기"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"글꼴 크기"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"축소"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"확대"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"확대 창"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"확대 창 컨트롤"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"확대"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{설정이 #개 추가되었습니다.}other{설정이 #개 추가되었습니다.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"삭제됨"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>을(를) 추가할까요?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> 앱을 추가하면 이 패널에 컨트롤과 콘텐츠가 추가됩니다. 일부 앱에서는 여기 표시되는 컨트롤을 선택할 수 있습니다."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> 컨트롤을 삭제할까요?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"즐겨찾기에 추가됨"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"즐겨찾기에 추가됨, 위치 <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"즐겨찾기에서 삭제됨"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"기타"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"기기 컨트롤에 추가"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"추가"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"삭제"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g>에서 제안"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"기기 잠김"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"잠금 화면에서 기기를 표시하고 제어하시겠습니까?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"외부 기기에 대한 제어 권한을 잠금 화면에 추가할 수 있습니다.\n\n기기 앱을 사용하여 휴대전화나 태블릿의 잠금을 해제하지 않고 해당 기기를 제어할 수도 있습니다.\n\n언제든지 설정에서 옵션을 변경할 수 있습니다."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"잠금 화면에서 기기를 제어하시겠습니까?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"휴대전화나 태블릿의 화면을 잠금 해제하지 않고 해당 기기를 제어할 수 있습니다.\n\n기기 앱에 이러한 방식으로 어떤 기기를 제어할 수 있는지 표시됩니다."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"아니요"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"예"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN에 문자나 기호가 포함됨"</string>
@@ -880,8 +880,9 @@
<string name="controls_error_generic" msgid="352500456918362905">"통계를 로드할 수 없음"</string>
<string name="controls_error_failed" msgid="960228639198558525">"오류. 다시 시도하세요."</string>
<string name="controls_menu_add" msgid="4447246119229920050">"컨트롤 추가"</string>
- <string name="controls_menu_edit" msgid="890623986951347062">"컨트롤 수정"</string>
+ <string name="controls_menu_edit" msgid="890623986951347062">"제어 설정 수정"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"앱 추가"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"앱 삭제"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"출력 추가"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"그룹"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"기기 1대 선택됨"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"방송할 수 없음"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"저장할 수 없습니다. 다시 시도해 주세요."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"저장할 수 없습니다."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"4자 이상 입력하세요."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16자 미만이어야 합니다."</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• 1대 이상의 기기를 사용할 수 있습니다."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"바로가기를 길게 터치하세요."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"취소"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"지금 화면 전환"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"휴대전화 펼치기"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"화면을 전환할까요?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"해상도를 높이려면 후면 카메라를 사용하세요."</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"해상도를 높이려면 후면 카메라를 사용하세요."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"폴더블 기기를 펼치는 모습"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"폴더블 기기를 뒤집는 모습"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"배터리 <xliff:g id="PERCENTAGE">%s</xliff:g> 남음"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"직장 프로필로 전환"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"닫기"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"잠금 화면 설정"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi를 사용할 수 없음"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"카메라 차단됨"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"카메라 및 마이크 차단됨"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"마이크 차단됨"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"우선순위 모드 설정됨"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/tiles_states_strings.xml b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
index c3d9d44db26a..7981d285946c 100644
--- a/packages/SystemUI/res/values-ko/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"꺼짐"</item>
<item msgid="5966994759929723339">"켜짐"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"사용 불가"</item>
+ <item msgid="2478289035899842865">"사용 안함"</item>
+ <item msgid="5137565285664080143">"사용"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 834d1bf69577..1237679ff4fb 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Эгер PIN кодду дагы бир жолу туура эмес киргизсеңиз, жумуш профилиңиз жана андагы маалыматтын баары өчөт."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Эгер сырсөздү дагы бир жолу туура эмес киргизсеңиз, жумуш профилиңиз жана андагы маалыматтын баары өчөт."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Манжа изинин сенсорун басыңыз"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Манжа изинин сүрөтчөсү"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Жүз таанылбай жатат. Манжа изин колдонуңуз."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Жумуштун кулпуланган экраны"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Жабуу"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Жарыктыгы"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Түстөрдү инверсиялоо"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Түстөрдү тууралоо"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Ариптин өлчөмү"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Колдонуучуларды тескөө"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Бүттү"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Жабуу"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"экранды жаздыруу"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Аталышы жок"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Көшүү режими"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Арип өлчөмү"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Кичирейтүү"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Чоңойтуу"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Чоңойтуу терезеси"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Чоңойтуу терезесин башкаруу каражаттары"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Жакындатуу"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# көзөмөл кошулду.}other{# көзөмөл кошулду.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Өчүрүлдү"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> кошулсунбу?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> колдонмосун кошсоңуз, ал бул панелге башкаруу элементтерин жана контентти кошо алат. Айрым колдонмолордо бул жерде көрүнүүчү башкаруу элементтерин тандай аласыз."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> башкаруу элементтери өчүрүлсүнбү?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Сүйүктүүлөргө кошулду"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Сүйүктүүлөргө <xliff:g id="NUMBER">%d</xliff:g>-позицияга кошулду"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Сүйүктүүлөрдөн чыгарылды"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Башка"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Түзмөктү башкаруу элементтерине кошуу"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Кошуу"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Өчүрүү"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> сунуштайт"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Түзмөк кулпуланды"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Түзмөктөрдү кулпуланган экрандан көрүп, көзөмөлдөйсүзбү?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Тышкы түзмөктөрүңүздү көзөмөлдөө каражаттарын кулпу экранына кошо аласыз.\n\nТүзмөгүңүздүн колдонмосу айрым түзмөктөрдү телефонуңуздун же планшетиңиздин кулпусун ачпастан көзөмөлдөөгө уруксат бериши мүмкүн.\n\nКаалаган убакта Жөндөөлөрдөн өзгөртүүлөрдү жасай аласыз."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Түзмөктөрдү кулпуланган экрандан көзөмөлдөйсүзбү?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Айрым түзмөктөрдү телефонуңуздун же планшетиңиздин кулпусун ачпастан көзөмөлдөй аласыз.\n\nКайсы түзмөктөрдү ушул жол менен көзөмөлдөөгө болорун түзмөгүңүздүн колдонмосу аныктайт."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Жок, рахмат"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ооба"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN код тамгалардан же символдордон турат"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Башкаруу элементтерин кошуу"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Башкаруу элементтерин түзөтүү"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Колдонмо кошуу"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Колдонмону алып салуу"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Медиа түзмөктөрдү кошуу"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Топ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 түзмөк тандалды"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Кабарлоого болбойт"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Сакталган жок. Кайталап көрүңүз."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Сакталган жок."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Кеминде 4 символдон турушу керек"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 символдон ашпашы керек"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Кеминде бир түзмөк жеткиликтүү"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Ыкчам баскычты басып туруңуз"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Токтотуу"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Экрандарды азыр которуштуруу"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Телефонду жайып алыңыз"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Экрандар которуштурулсунбу?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Жогорку дааналык үчүн арткы камераны колдонуңуз"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Жогорку дааналык үчүн телефондун арткы камерасын колдонуңуз"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ачылып турган бүктөлмө түзмөк"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Оодарылып жаткан бүктөлмө түзмөк"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Батареянын кубаты: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Жумуш профилине которулуу"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Жабуу"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Кулпуланган экран параметрлери"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi жеткиликтүү эмес"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера бөгөттөлдү"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера менен микрофон бөгөттөлдү"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон бөгөттөлдү"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Маанилүү сүйлөшүүлөр режими күйүк"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/tiles_states_strings.xml b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
index f4b84478d56b..0f277f9de292 100644
--- a/packages/SystemUI/res/values-ky/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Өчүк"</item>
<item msgid="5966994759929723339">"Күйүк"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Жеткиликсиз"</item>
+ <item msgid="2478289035899842865">"Өчүк"</item>
+ <item msgid="5137565285664080143">"Күйүк"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index ac81dccecc0a..908aac4a7b7f 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -63,7 +63,11 @@
<dimen name="large_dialog_width">348dp</dimen>
<dimen name="qs_panel_padding_top">@dimen/qqs_layout_margin_top</dimen>
- <dimen name="qs_panel_padding_top_combined_headers">@dimen/qs_panel_padding_top</dimen>
- <dimen name="controls_padding_horizontal">16dp</dimen>
+ <dimen name="controls_header_horizontal_padding">12dp</dimen>
+ <dimen name="controls_content_margin_horizontal">16dp</dimen>
+
+ <!-- Bouncer user switcher margins -->
+ <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">0dp</dimen>
+ <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 0b4c2dc2ae00..843c87a6c524 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ຫາກທ່ານໃສ່ລະຫັດ PIN ຜິດໃນຄວາມພະຍາຍາມເທື່ອຕໍ່ໄປ, ໂປຣໄຟລ໌ບ່ອນເຣັດວຽກຂອງທ່ານ ແລະ ຂໍ້ມູນຂອງມັນຈະຖືກລຶບອອກ."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ຫາກທ່ານໃສ່ລະຫັດຜິດໃນຄວາມພະຍາຍາມເທື່ອຕໍ່ໄປ, ໂປຣໄຟລ໌ບ່ອນເຣັດວຽກຂອງທ່ານ ແລະ ຂໍ້ມູນຂອງມັນຈະຖືກລຶບອອກ."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ແຕະໃສ່ເຊັນເຊີລາຍນິ້ວມື"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ໄອຄອນລາຍນິ້ວມື"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ບໍ່ສາມາດຈຳແນກໜ້າໄດ້. ກະລຸນາໃຊ້ລາຍນິ້ວມືແທນ."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"ໜ້າຈໍລັອກວຽກ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ປິດ"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ຄວາມແຈ້ງ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ການປີ້ນສີ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ການແກ້ໄຂສີ"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ຂະໜາດຟອນ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ຈັດການຜູ້ໃຊ້"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ແລ້ວໆ"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ປິດ"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ການບັນທຶກໜ້າຈໍ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ບໍ່ມີຊື່"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ສະແຕນບາຍ"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ຂະໜາດຟອນ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ເຮັດໃຫ້ນ້ອຍລົງ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ເຮັດໃຫ້ໃຫຍ່ຂຶ້ນ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ໜ້າຈໍການຂະຫຍາຍ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ການຄວບຄຸມໜ້າຈໍການຂະຫຍາຍ"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ຊູມເຂົ້າ"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{ເພີ່ມ # ການຄວບຄຸມແລ້ວ.}other{ເພີ່ມ # ການຄວບຄຸມແລ້ວ.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"ລຶບອອກແລ້ວ"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"ເພີ່ມ <xliff:g id="APPNAME">%s</xliff:g> ບໍ?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"ເມື່ອທ່ານເພີ່ມ <xliff:g id="APPNAME">%s</xliff:g>, ມັນຈະສາມາດເພີ່ມການຄວບຄຸມ ແລະ ເນື້ອຫາໃສ່ແຜງນີ້ໄດ້. ໃນບາງແອັບ, ທ່ານສາມາດເລືອກວ່າຈະໃຫ້ສ່ວນຄວບຄຸມໃດສະແດງຂຶ້ນຢູ່ບ່ອນນີ້ໄດ້."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"ລຶບການຄວບຄຸມສຳລັບ <xliff:g id="APPNAME">%s</xliff:g> ອອກບໍ?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"ເພີ່ມລາຍການທີ່ມັກແລ້ວ"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"ເພີ່ມລາຍການທີ່ມັກແລ້ວ, ຕຳແໜ່ງ <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ຍົກເລີກລາຍການທີ່ມັກແລ້ວ"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ອື່ນໆ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ເພີ່ມໃສ່ການຄວບຄຸມອຸປະກອນ"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ເພີ່ມ"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"ລຶບອອກ"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"ແນະນຳໂດຍ <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"ອຸປະກອນຖືກລັອກໄວ້"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ສະແດງ ແລະ ຄວບຄຸມອຸປະກອນຈາກໜ້າຈໍລັອກບໍ?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ທ່ານສາມາດເພີ່ມການຄວບຄຸມສຳລັບອຸປະກອນພາຍນອກຂອງທ່ານໄປໃສ່ໜ້າຈໍລັອກໄດ້.\n\nແອັບອຸປະກອນຂອງທ່ານອາດອະນຸຍາດໃຫ້ທ່ານຄວບຄຸມອຸປະກອນບາງຢ່າງໄດ້ໂດຍບໍ່ຕ້ອງປົດລັອກໂທລະສັບ ຫຼື ແທັບເລັດຂອງທ່ານ.\n\nທ່ານສາມາດປ່ຽນແປງຕອນໃດກໍໄດ້ໃນການຕັ້ງຄ່າ."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ຄວບຄຸມອຸປະກອນຈາກໜ້າຈໍລັອກບໍ?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"ທ່ານສາມາດຄວບຄຸມອຸປະກອນບາງຢ່າງໄດ້ໂດຍບໍ່ຕ້ອງປົດລັອກໂທລະສັບ ຫຼື ແທັບເລັດຂອງທ່ານ.\n\nແອັບອຸປະກອນຂອງທ່ານຈະກຳນົດວ່າອຸປະກອນໃດສາມາດຖືກຄວບຄຸມດ້ວຍວິທີນີ້ໄດ້."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ບໍ່, ຂອບໃຈ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ແມ່ນແລ້ວ"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ປະກອບມີຕົວອັກສອນ ຫຼື ສັນຍາລັກ"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"ເພີ່ມການຄວບຄຸມ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ແກ້ໄຂການຄວບຄຸມ"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"ເພີ່ມແອັບ"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"ລຶບແອັບອອກ"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"ເພີ່ມເອົ້າພຸດ"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"ກຸ່ມ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"ເລືອກ 1 ອຸປະກອນແລ້ວ"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ມີຢ່າງໜ້ອຍ 1 ອຸປະກອນພ້ອມໃຫ້ນຳໃຊ້"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ແຕະທາງລັດຄ້າງໄວ້"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ຍົກເລີກ"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ສະຫຼັບໜ້າຈໍດຽວນີ້"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ພືໂທລະສັບອອກ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ສະຫຼັບໜ້າຈໍບໍ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ເພື່ອຄວາມລະອຽດທີ່ສູງຂຶ້ນ, ໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບຫຼັງ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ເພື່ອຄວາມລະອຽດທີ່ສູງຂຶ້ນ, ໃຫ້ປີ້ນໂທລະສັບ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ອຸປະກອນທີ່ພັບໄດ້ກຳລັງກາງອອກ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ອຸປະກອນທີ່ພັກໄດ້ກຳລັງປີ້ນໄປມາ"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"ແບັດເຕີຣີເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ສະຫຼັບໄປໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ປິດ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ການຕັ້ງຄ່າໜ້າຈໍລັອກ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ບໍ່ພ້ອມໃຫ້ນຳໃຊ້"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ກ້ອງຖ່າຍຮູບຖືກບລັອກຢູ່"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ກ້ອງຖ່າຍຮູບ ແລະ ໄມໂຄຣໂຟນຖືກບລັອກຢູ່"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ໄມໂຄຣໂຟນຖືກບລັອກຢູ່"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ໂໝດຄວາມສຳຄັນເປີດຢູ່"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/tiles_states_strings.xml b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
index f7f4b623402c..d54cf4d24181 100644
--- a/packages/SystemUI/res/values-lo/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"ປິດ"</item>
<item msgid="5966994759929723339">"ເປີດ"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ບໍ່ສາມາດເບິ່ງໄດ້"</item>
+ <item msgid="2478289035899842865">"ປິດ"</item>
+ <item msgid="5137565285664080143">"ເປີດ"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 583624f7182d..81449d0f16a3 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jei kitu bandymu įvesite netinkamą PIN kodą, darbo profilis ir jo duomenys bus ištrinti."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Jei kitu bandymu įvesite netinkamą slaptažodį, darbo profilis ir jo duomenys bus ištrinti."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Palieskite piršto antspaudo jutiklį"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Piršto antspaudo piktograma"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Veidas neatpažintas. Naudokite kontrolinį kodą."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pranešimų gaubtas."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Spartieji nustatymai."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Spartieji nustatymai ir pranešimų skydelis."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Užrakinimo ekranas."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Darbo profilio užrakinimo ekranas"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Uždaryti"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Šviesumas"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Spalvų inversija"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Spalvų taisymas"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Šrifto dydis"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Tvarkyti naudotojus"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Atlikta"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Uždaryti"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekrano įrašymas"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nėra pavadinimo"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Budėjimo laikas"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Šrifto dydis"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Padaryti mažesnius"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Padaryti didesnius"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Didinimo langas"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Didinimo lango valdikliai"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Artinti"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Pridėtas # valdiklis.}one{Pridėtas # valdiklis.}few{Pridėti # valdikliai.}many{Pridėta # valdiklio.}other{Pridėta # valdiklių.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Pašalinta"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Pridėti „<xliff:g id="APPNAME">%s</xliff:g>“?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Pridėjus programą „<xliff:g id="APPNAME">%s</xliff:g>“, ji gali pridėti valdiklių ir turinio prie šio skydelio. Kai kuriose programose galite pasirinkti, kurie valdikliai čia rodomi."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Pašalinti „<xliff:g id="APPNAME">%s</xliff:g>“ valdiklius?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Įtraukta į mėgstamiausius"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Įtraukta į mėgstamiausius, padėtis: <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Pašalinta iš mėgstamiausių"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Kita"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Pridėjimas prie įrenginio valdiklių"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Pridėti"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Pašalinti"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Siūlo „<xliff:g id="APP">%s</xliff:g>“"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Įrenginys užrakintas"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Rodyti ir valdyti įrenginius užrakinimo ekrane?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Galite pridėti išorinių įrenginių valdiklių užrakinimo ekrane.\n\nĮrenginio programoje gali būti leidžiama valdyti tam tikrus įrenginius neatrakinus telefono ar planšetinio kompiuterio.\n\nGalite bet kada pakeisti „Nustatymų“ skiltyje."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Valdyti įrenginius užrakinimo ekrane?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Galite valdyti tam tikrus išorinius įrenginius neatrakinę telefono ar planšetinio kompiuterio.\n\nĮrenginio programoje nustatoma, kuriuos įrenginius galima valdyti tokiu būdu."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, ačiū"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Taip"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN kodą sudaro raidės arba simboliai"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Pridėti valdiklių"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Redaguoti valdiklius"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Pridėti programą"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Pašalinti programą"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Išvesčių pridėjimas"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupė"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Pasirinktas 1 įrenginys"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Pasiekiamas bent vienas įrenginys"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Perjungti ekranus dabar"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Atlenkite telefoną"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Perjungti ekranus?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Didesnei raiškai naudokite galinį fotoaparatą"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Kad raiška būtų geresnė, apverskite telefoną"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Lankstomasis įrenginys išlankstomas"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Lankstomasis įrenginys apverčiamas"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Liko akumuliatoriaus įkrovos: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Perjungti į darbo profilį"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Uždaryti"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Užrakinimo ekrano nustatymai"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"„Wi-Fi“ ryšys nepasiekiamas"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Fotoaparatas užblokuotas"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Fotoaparatas ir mikrofonas užblokuoti"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonas užblokuotas"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteto režimas įjungtas"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/tiles_states_strings.xml b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
index 58379150e4a7..e66f590364dd 100644
--- a/packages/SystemUI/res/values-lt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Išjungta"</item>
<item msgid="5966994759929723339">"Įjungta"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nepasiekiama"</item>
+ <item msgid="2478289035899842865">"Išjungta"</item>
+ <item msgid="5137565285664080143">"Įjungta"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 2b68f2ae6a1b..5838e259b02c 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ja nākamajā mēģinājumā ievadīsiet nepareizu PIN, jūsu darba profils un ar to saistītie dati tiks dzēsti."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ja nākamajā mēģinājumā ievadīsiet nepareizu paroli, jūsu darba profils un ar to saistītie dati tiks dzēsti."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Pieskarieties pirksta nospieduma sensoram"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Pirksta nospieduma ikona"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nevar atpazīt seju. Lietojiet pirksta nospiedumu."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -187,8 +186,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"Akumulators: <xliff:g id="NUMBER">%d</xliff:g> procenti"</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$d</xliff:g>%%, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Notiek akumulatora uzlāde, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%d</xliff:g>%%, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$d</xliff:g>%%, <xliff:g id="TIME">%2$s</xliff:g>, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%d</xliff:g>, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$d</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"Skatīt visus paziņojumus"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletaips ir iespējots."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Zvana signāls — vibrācija."</string>
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Paziņojumu panelis"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ātrie iestatījumi"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ātrie iestatījumi un paziņojumu panelis."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Bloķēšanas ekrāns."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Darba profila bloķēšanas ekrāns"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Aizvērt"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Spilgtums"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Krāsu inversija"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Krāsu korekcija"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Fonta lielums"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Pārvaldīt lietotājus"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Gatavs"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Aizvērt"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekrāna ierakstīšana"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nav nosaukuma"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Gaidstāve"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Fonta lielums"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Samazināt"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Palielināt"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Palielināšanas logs"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Palielināšanas loga vadīklas"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Tuvināt"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Pievienota # vadīkla.}zero{Pievienotas # vadīklas.}one{Pievienota # vadīkla.}other{Pievienotas # vadīklas.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Noņemta"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Vai pievienot lietotni <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Ja pievienosiet lietotni <xliff:g id="APPNAME">%s</xliff:g>, tā varēs pievienot vadīklas un saturu šim panelim. Dažās lietotnēs varat izvēlēties, kuras vadīklas šeit rādīt."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vai noņemt vadīklas lietotnei <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Pievienota izlasei"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Pievienota izlasei, <xliff:g id="NUMBER">%d</xliff:g>. pozīcija"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Noņemta no izlases"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Cita"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Pievienošana ierīču vadīklām"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Pievienot"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Noņemt"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Ieteica: <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Ierīce ir bloķēta"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vai skatīt un kontrolēt ierīces no bloķēšanas ekrāna?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Varat pievienot bloķēšanas ekrānam vadīklas, ar kurām kontrolēt savas ārējās ierīces.\n\nJūsu ierīces lietotne var ļaut jums kontrolēt dažas ierīces, neatbloķējot tālruni vai planšetdatoru.\n\nVarat jebkurā laikā veikt izmaiņas iestatījumos."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vai kontrolēt ierīces no bloķēšanas ekrāna?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Varat kontrolēt dažas ierīces, neatbloķējot tālruni vai planšetdatoru.\n\nJūsu ierīces lietotne nosaka, kuras ierīces var šādi kontrolēt."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nē, paldies"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Jā"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ietver burtus vai simbolus."</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Pievienot vadīklas"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Rediģēt vadīklas"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Pievienot lietotni"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Noņemt lietotni"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Izejas ierīču pievienošana"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Atlasīta viena ierīce"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Nevar apraidīt"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Izmantojiet vismaz 4 rakstzīmes"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Izmantojiet mazāk nekā 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ir pieejama vismaz viena ierīce."</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Mainīt ekrānus tagad"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Tālruņa atlocīšana"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vai mainīt ekrānus?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Lai izmantotu augstāku izšķirtspēju, lietojiet aizmugurējo kameru"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Lai izmantotu augstāku izšķirtspēju, apvērsiet tālruni"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Salokāma ierīce tiek atlocīta"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Salokāma ierīce tiek apgriezta"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Atlikušais uzlādes līmenis: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Pārslēgties uz darba profilu"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Aizvērt"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Bloķēšanas ekrāna iestatījumi"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nav pieejams"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera ir bloķēta"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameras un mikrofona lietošana ir bloķēta"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofons ir bloķēts"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritātes režīms ir ieslēgts"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/tiles_states_strings.xml b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
index 9a534c4eaeed..d32efec81a99 100644
--- a/packages/SystemUI/res/values-lv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Izslēgts"</item>
<item msgid="5966994759929723339">"Ieslēgts"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nav pieejams"</item>
+ <item msgid="2478289035899842865">"Izslēgts"</item>
+ <item msgid="5137565285664080143">"Ieslēgts"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 3ba3bc067fd6..6f560f1f4e11 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ако внесете погрешен PIN при следниот обид, работниот профил и неговите податоци ќе се избришат."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ако внесете погрешна лозинка при следниот обид, работниот профил и неговите податоци ќе се избришат."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Допрете го сензорот за отпечатоци"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Икона за отпечаток"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не се препознава ликот. Користете отпечаток."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Работен заклучен екран"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Затвори"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Осветленост"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Инверзија на боите"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекција на боите"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Големина на фонтот"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Управувајте со корисниците"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Готово"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Затвори"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"снимање на екранот"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без наслов"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Подготвеност"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Големина на фонтот"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Намали"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Зголеми"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за зголемување"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроли на прозорец за зголемување"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Зумирај"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Додадена е # контрола.}one{Додадени се # контрола.}other{Додадени се # контроли.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Отстранета"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Да се додаде <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Кога ќе ја додадете <xliff:g id="APPNAME">%s</xliff:g>, таа ќе може да додава контроли и содржини на таблава. Кај некои апликации, може да изберете кои контроли ќе се прикажуваат тука."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Да се отстранат контролите за <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Омилена"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Омилена, позиција <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Неомилена"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Друга"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Додајте во контроли за уредите"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Додај"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Отстрани"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Предложено од <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Уредот е заклучен"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Да се прикажуваат и контролираат уреди од заклучениот екран?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Може да додадете контроли за надворешните уреди на заклучениот екран.\n\nАпликацијата на уредот може да ви дозволи да контролирате одредени уреди без да го отклучувате телефонот или таблетот.\n\nМоже да извршите промени во секое време во „Поставки“."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Да се контролираат уреди од заклучен екран?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Може да контролирате одредени уреди без отклучување на телефонот или таблетот.\n\nАпликацијата на вашиот уред одредува кои уреди може да се контролираат вака."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Не, фала"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Да"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-кодот содржи букви или симболи"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Додајте контроли"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Изменете ги контролите"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Додајте апликација"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Отстранете ја апликацијата"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Додајте излези"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Избран е 1 уред"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Не може да се емитува"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не може да се зачува. Обидете се повторно."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не може да се зачува."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Употребете најмалку 4 знаци"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Употребете помалку од 16 знаци"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• достапен е најмалку еден уред"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Допрете и задржете ја кратенката"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Откажи"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Променете го екранот сега"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Отворете го телефонот"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Да се промени екранот?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Користете ја задната камера за да добиете повисока резолуција"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Отворете го телефонот за да добиете повисока резолуција"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Преклопувачки уред се отклопува"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Преклопувачки уред се врти"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Преостаната батерија: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Префрли се на работен профил"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Затвори"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Поставки за заклучен екран"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi не е достапно"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камерата е блокирана"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камерата и микрофонот се блокирани"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофонот е блокиран"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетниот режим е вклучен"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
index d088f120b362..8c4459a9ae6e 100644
--- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Исклучено"</item>
<item msgid="5966994759929723339">"Вклучено"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Недостапно"</item>
+ <item msgid="2478289035899842865">"Исклучено"</item>
+ <item msgid="5137565285664080143">"Вклучено"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 123c42447b18..aaadab534131 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പിൻ നൽകിയാൽ, നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലും അതിന്റെ ഡാറ്റയും ഇല്ലാതാക്കപ്പെടും."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പാസ്‌വേഡ് നൽകിയാൽ, നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലും അതിന്റെ ഡാറ്റയും ഇല്ലാതാക്കപ്പെടും."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ഫിംഗർപ്രിന്റ് സെൻസർ സ്‌പർശിക്കുക"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ഫിംഗർപ്രിന്റ് ഐക്കൺ"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"മുഖം തിരിച്ചറിയാനായില്ല. പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"ഔദ്യോഗിക ലോക്ക് സ്ക്രീൻ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"അവസാനിപ്പിക്കുക"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"തെളിച്ചം"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"നിറം വിപരീതമാക്കൽ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"നിറം ശരിയാക്കൽ"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ഫോണ്ട് വലുപ്പം"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ഉപയോക്താക്കളെ മാനേജ് ചെയ്യുക"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"പൂർത്തിയാക്കി"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"അടയ്ക്കുക"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"സ്ക്രീൻ റെക്കോർഡിംഗ്"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"പേരില്ല"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"സ്‌റ്റാൻഡ്‌ബൈ"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ഫോണ്ട് വലുപ്പം"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ചെറുതാക്കുക"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"വലുതാക്കുക"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ നിയന്ത്രണങ്ങൾ"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"സൂം ഇൻ ചെയ്യുക"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# നിയന്ത്രണം ചേർത്തു.}other{# നിയന്ത്രണങ്ങൾ ചേർത്തു.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"നീക്കം ചെയ്‌തു"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ചേർക്കണോ?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"നിങ്ങൾ <xliff:g id="APPNAME">%s</xliff:g> ചേർത്താൽ, അതിന് ഈ പാനലിലേക്ക് നിയന്ത്രണങ്ങളും ഉള്ളടക്കവും ചേർക്കാനാകും. ചില ആപ്പുകളിൽ, ഇവിടെ ഏത് നിയന്ത്രണങ്ങൾ ദൃശ്യമാകണമെന്ന് നിങ്ങൾക്ക് തിരഞ്ഞെടുക്കാനാകും."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> എന്നതിനുള്ള നിയന്ത്രണങ്ങൾ നീക്കം ചെയ്യണോ?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"പ്രിയപ്പെട്ടതാക്കി"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"പ്രിയപ്പെട്ടതാക്കി, സ്ഥാനം <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"പ്രിയപ്പെട്ടതല്ലാതാക്കി"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"മറ്റുള്ളവ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ഉപകരണ നിയന്ത്രണങ്ങളിലേക്ക് ചേർക്കുക"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ചേർക്കുക"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"നീക്കം ചെയ്യുക"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> നിർദ്ദേശിച്ചത്"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"ഉപകരണം ലോക്ക് ചെയ്തു"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ലോക്ക് സ്‌ക്രീനിൽ നിന്ന് ഉപകരണങ്ങൾ കാണിക്കുകയും നിയന്ത്രിക്കുകയും ചെയ്യണോ?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"നിങ്ങളുടെ ബാഹ്യ ഉപകരണങ്ങൾക്കുള്ള നിയന്ത്രണങ്ങൾ ലോക്ക് സ്‌ക്രീനിലേക്ക് ചേർക്കാനാകും.\n\nനിങ്ങളുടെ ഫോണോ ടാബ്‌ലെറ്റോ അൺലോക്ക് ചെയ്യാതെ ചില ഉപകരണങ്ങൾ നിയന്ത്രിക്കാൻ നിങ്ങളുടെ ഉപകരണ ആപ്പ് അനുവദിച്ചേക്കും.\n\nനിങ്ങൾക്ക് ക്രമീകരണത്തിൽ ഏതുസമയത്തും മാറ്റങ്ങൾ വരുത്താം."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ലോക്ക് സ്‌ക്രീനിൽ നിന്ന് ഉപകരണങ്ങൾ നിയന്ത്രിക്കണോ?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"നിങ്ങളുടെ ഫോണോ ടാബ്‌ലെറ്റോ അൺലോക്ക് ചെയ്യാതെ ചില ഉപകരണങ്ങൾ നിയന്ത്രിക്കാം.\n\nഏതൊക്കെ ഉപകരണങ്ങൾ ഈ രീതിയിൽ നിയന്ത്രിക്കാൻ കഴിയുമെന്ന് നിങ്ങളുടെ ഉപകരണ ആപ്പ് നിർണ്ണയിക്കുന്നു."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"വേണ്ട, നന്ദി"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ഉവ്വ്"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"പിന്നിൽ അക്ഷരങ്ങളോ ചിഹ്നങ്ങളോ അടങ്ങിയിരിക്കുന്നു"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"നിയന്ത്രണങ്ങൾ ചേർക്കുക"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"നിയന്ത്രണങ്ങൾ എഡിറ്റ് ചെയ്യുക"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"ആപ്പ് ചേർക്കുക"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"ആപ്പ് നീക്കം ചെയ്യുക"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"ഔട്ട്പുട്ടുകൾ ചേർക്കുക"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"ഗ്രൂപ്പ്"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"ഒരു ഉപകരണം തിരഞ്ഞെടുത്തു"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ഒരു ഉപകരണമെങ്കിലും ലഭ്യമാണ്"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"സ്പർശിച്ച് പിടിക്കുക കുറുക്കുവഴി"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"റദ്ദാക്കുക"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ഇപ്പോൾ സ്ക്രീനുകൾ മാറുക"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ഫോൺ അൺഫോൾഡ് ചെയ്യൽ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"സ്ക്രീനുകൾ മാറണോ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ഉയർന്ന റെസല്യൂഷന്, പിൻ ക്യാമറ ഉപയോഗിക്കുക"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ഉയർന്ന റെസല്യൂഷന്, ഫോൺ ഫ്ലിപ്പ് ചെയ്യുക"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ഫോൾഡ് ചെയ്യാവുന്ന ഉപകരണം അൺഫോൾഡ് ആകുന്നു"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ഫോൾഡ് ചെയ്യാവുന്ന ഉപകരണം, കറങ്ങുന്ന വിധത്തിൽ ഫ്ലിപ്പ് ആകുന്നു"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ബാറ്ററി ചാർജ് ശേഷിക്കുന്നു"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ഔദ്യോഗിക പ്രൊഫൈലിലേക്ക് മാറുക"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"അടയ്ക്കുക"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ലോക്ക് സ്ക്രീൻ ക്രമീകരണം"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"വൈഫൈ ലഭ്യമല്ല"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ക്യാമറ ബ്ലോക്ക് ചെയ്തിരിക്കുന്നു"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ക്യാമറയും മൈക്രോഫോണും ബ്ലോക്ക് ചെയ്തിരിക്കുന്നു"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"മൈക്രോഫോൺ ബ്ലോക്ക് ചെയ്തിരിക്കുന്നു"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"മുൻഗണനാ മോഡ് ഓണാണ്"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/tiles_states_strings.xml b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
index 108e173e003a..62bac5cd1212 100644
--- a/packages/SystemUI/res/values-ml/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"ഓഫാണ്"</item>
<item msgid="5966994759929723339">"ഓണാണ്"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ലഭ്യമല്ല"</item>
+ <item msgid="2478289035899842865">"ഓഫാണ്"</item>
+ <item msgid="5137565285664080143">"ഓണാണ്"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index d74e7dc56194..ba64ca8385dd 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Та дараагийн оролдлогоор буруу ПИН оруулбал таны ажлын профайлыг өгөгдөлтэй нь цуг устгах болно."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Та дараагийн оролдлогоор буруу нууц үг оруулбал таны ажлын профайлыг өгөгдөлтэй нь цуг устгах болно."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Хурууны хээ мэдрэгчид хүрэх"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Хурууны хээний дүрс тэмдэг"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Царай таних боломжгүй. Оронд нь хурууны хээ ашигла"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Ажлын түгжигдсэн дэлгэц"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Хаах"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Тодрол"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Өнгө хувиргалт"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Өнгө тохируулга"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Фонтын хэмжээ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Хэрэглэгчдийг удирдах"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Дууссан"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Хаах"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"дэлгэцийн бичлэг"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Гарчиггүй"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Зогсолтын горим"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Фонтын хэмжээ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Жижгэрүүлэх"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Томруулах"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Томруулалтын цонх"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Томруулалтын цонхны хяналт"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Томруулах"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# хяналт нэмсэн.}other{# хяналт нэмсэн.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Хассан"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>-г нэмэх үү?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Та <xliff:g id="APPNAME">%s</xliff:g>-г нэмэх үед энэ нь уг түр зуурын самбарт тохиргоо болон контент нэмэх боломжтой. Зарим аппад та энд ямар тохиргоог харуулахыг сонгох боломжтой."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g>-н тохиргоог хасах уу?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Дуртай гэж тэмдэглэсэн"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>-р байршилд дуртай гэж тэмдэглэсэн"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Дургүй гэж тэмдэглэсэн"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Бусад"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Төхөөрөмжийн хяналт руу нэмэх"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Нэмэх"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Хасах"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g>-н санал болгосон"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Төхөөрөмжийг түгжсэн"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Түгжигдсэн дэлгэцээс төхөөрөмжүүдийг харуулж, хянах уу?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Та түгжигдсэн дэлгэцэд гадаад төхөөрөмжүүдийнхээ хяналтыг нэмэх боломжтой.\n\nТаны төхөөрөмжийн апп танд утас эсвэл таблетынхаа түгжээг тайлахгүйгээр зарим төхөөрөмжийг хянах боломжийг олгож магадгүй.\n\nТа хүссэн үедээ Тохиргоонд өөрчлөлт хийж болно."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Төхөөрөмжүүдийг түгжигдсэн дэлгэцээс хянах уу?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Та утас эсвэл таблетынхаа түгжээг тайлахгүйгээр зарим төхөөрөмжийг хянах боломжтой.\n\nТаны төхөөрөмжийн апп энэ аргаар ямар төхөөрөмжүүдийг хянах боломжтойг тодорхойлно."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Үгүй, баярлалаа"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Тийм"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ПИН нь үсэг эсвэл дүрс тэмдэгт агуулдаг"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Хяналт нэмэх"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Хяналтыг өөрчлөх"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Апп нэмэх"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Аппыг хасах"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Гаралт нэмэх"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Бүлэг"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 төхөөрөмж сонгосон"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Нэвтрүүлэх боломжгүй"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Хадгалах боломжгүй. Дахин оролдоно уу."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Хадгалах боломжгүй."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Дор хаяж 4 тэмдэгт ашиглана уу."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16-аас цөөн тэмдэгт ашиглана уу"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Дор хаяж нэг төхөөрөмж боломжтой"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Товчлолд хүрээд удаан дарна уу"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Цуцлах"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Одоо дэлгэцүүдийг сэлгэх"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Утсыг дэлгэх"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Дэлгэцүүдийг сэлгэх үү?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Илүү өндөр нягтрал авах бол ар талын камерыг ашиглана уу"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Илүү өндөр нягтрал авах бол утсыг хөнтөрнө үү"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Эвхэгддэг төхөөрөмжийг дэлгэж байна"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Эвхэгддэг төхөөрөмжийг хөнтөрч байна"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> батарей үлдлээ"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Ажлын профайл руу сэлгэх"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Хаах"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Түгжигдсэн дэлгэцийн тохиргоо"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi боломжгүй байна"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камерыг блоклосон"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камер болон микрофоныг блоклосон"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофоныг блоклосон"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Чухал горим асаалттай байна"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/tiles_states_strings.xml b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
index 5cd21c1d2ec8..33f359672477 100644
--- a/packages/SystemUI/res/values-mn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Унтраалттай"</item>
<item msgid="5966994759929723339">"Асаалттай"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Боломжгүй"</item>
+ <item msgid="2478289035899842865">"Унтраалттай"</item>
+ <item msgid="5137565285664080143">"Асаалттай"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 3d73e2259c6e..955e586adaf6 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पिन एंटर केल्यास, तुमची कार्य प्रोफाइल आणि तिचा डेटा हटवला जाईल."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पासवर्ड एंटर केल्यास, तुमची कार्य प्रोफाइल आणि तिचा डेटा हटवला जाईल."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"फिंगरप्रिंट सेन्सरला स्पर्श करा"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"फिंगरप्रिंट आयकन"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"चेहरा ओळखू शकत नाही. त्याऐवजी फिंगरप्रिंट वापरा."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"कार्य लॉक स्क्रीन"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करा"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"चमक"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"कलर इन्व्हर्जन"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"रंग सुधारणा"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"फॉंटचा आकार"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"वापरकर्ते व्यवस्‍थापित करा"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"पूर्ण झाले"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"बंद करा"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"आता सुरू करा"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"सूचना नाहीत"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"नवीन सूचना नाहीत"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"जुन्या सूचना पहाण्यासाठी अनलॉक करा"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"जुन्या सूचना पाहण्यासाठी अनलॉक करा"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"हे डिव्हाइस तुमच्या पालकाने व्यवस्थापित केले आहे"</string>
<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>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"स्क्रीन रेकॉर्डिंग"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक नाही"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"स्टँडबाय"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"फॉंट आकार"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"आणखी लहान करा"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"आणखी मोठे करा"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"मॅग्निफिकेशन विंडो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"मॅग्निफिकेशन विंडो नियंत्रणे"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"झूम इन करा"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# नियंत्रण जोडले आहे.}other{# नियंत्रणे जोडली आहेत.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"काढून टाकले"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> जोडायचे आहे का?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"तुम्ही <xliff:g id="APPNAME">%s</xliff:g> जोडता, तेव्हा ते या पॅनलमध्ये नियंत्रणे आणि आशय जोडू शकते. येथे कोणती नियंत्रणे दाखवावीत ते तुम्ही काही अ‍ॅप्समध्ये निवडू शकता."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> साठी नियंत्रणे काढून टाकायची आहेत का?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"आवडले"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"आवडले, स्थान <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"नावडले"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"इतर"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"डिव्हाइस नियंत्रणांमध्ये जोडा"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"जोडा"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"काढून टाका"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ने सुचवले आहे"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"डिव्हाइस लॉक आहे"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"लॉक स्क्रीनवरून डिव्हाइस दाखवायचे आणि नियंत्रित करायचे का?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"तुम्ही तुमच्या बाह्य डिव्हाइससाठी लॉक स्क्रीनवर नियंत्रणे जोडू शकता.\n\nतुमचे डिव्हाइस अ‍ॅप तुम्हाला तुमचा फोन किंवा टॅबलेट अनलॉक न करता काही डिव्हाइस नियंत्रित करण्याची अनुमती देऊ शकते.\n\nतुम्ही सेटिंग्ज मध्ये कधीही बदल करू शकता."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"लॉक स्क्रीनवरून डिव्हाइस नियंत्रित करायची का?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"तुमचा फोन किंवा टॅबलेट अनलॉक न करता तुम्ही काही डिव्हाइस नियंत्रित करू शकता.\n\nतुमचे डिव्हाइस अ‍ॅप अशा प्रकारे कोणते डिव्हाइस नियंत्रित केले जाऊ शकतात हे निर्धारित करते."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"नाही, नको"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"होय"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"पिनमध्ये अक्षरे किंवा चिन्हे आहेत"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"नियंत्रणे जोडा"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"नियंत्रणे संपादित करा"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"अ‍ॅप जोडा"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"ॲप काढून टाका"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट जोडा"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"गट"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"एक डिव्हाइस निवडले"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ब्रॉडकास्ट करू शकत नाही"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेव्ह करू शकत नाही. पुन्हा प्रयत्न करा."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेव्ह करू शकत नाही."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"किमान चार वर्ण वापरा"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"१६ पेक्षा कमी वर्ण वापरा"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• किमान एक डिव्हाइस उपलब्ध करणे"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"स्पर्श करा आणि धरून ठेवा शॉर्टकट"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द करा"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"आता स्क्रीन स्विच करा"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"फोन उघडा"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"स्क्रीन स्विच करायच्या का?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"उच्च रेझोल्यूशनसाठी रीअर कॅमेरा वापरा"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"उच्च रेझोल्यूशनसाठी, फोन फ्लिप करा"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फोल्ड करता येण्यासारखे डिव्हाइस अनफोल्ड केले जात आहे"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फोल्ड करता येण्यासारखे डिव्हाइस आजूबाजूला फ्लिप केले जात आहे"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> बॅटरी शिल्लक आहे"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"कार्य प्रोफाइलवर स्विच करा"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"बंद करा"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"लॉक स्क्रीन सेटिंग्ज"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"वाय-फाय उपलब्ध नाही"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"कॅमेरा ब्लॉक केला"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"कॅमेरा आणि मायक्रोफोन ब्लॉक केले आहेत"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"मायक्रोफोन ब्लॉक केला"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राधान्य मोड सुरू आहे"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/tiles_states_strings.xml b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
index 78560c4314c6..24d3b47af961 100644
--- a/packages/SystemUI/res/values-mr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"बंद आहे"</item>
<item msgid="5966994759929723339">"सुरू आहे"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"उपलब्ध नाही"</item>
+ <item msgid="2478289035899842865">"बंद आहे"</item>
+ <item msgid="5137565285664080143">"सुरू आहे"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index c3408b7ad8e6..8ed68c43b47d 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jika anda memasukkan PIN yang salah pada percubaan seterusnya, profil kerja anda dan data profil itu akan dipadamkan."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Jika anda memasukkan kata laluan yang salah pada percubaan seterusnya, profil kerja anda dan data profil itu akan dipadamkan."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sentuh penderia cap jari"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikon cap jari"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tidak mengenali wajah. Gunakan cap jari."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bidai pemberitahuan."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tetapan pantas."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Tetapan pantas dan Bidai pemberitahuan."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kunci skrin."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrin kunci kerja"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Kecerahan"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Penyongsangan warna"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Pembetulan warna"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Saiz fon"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Urus pengguna"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Selesai"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Tutup"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"rakaman skrin"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Tiada tajuk"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Tunggu sedia"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Saiz Fon"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Kecilkan"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Besarkan"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Tetingkap Pembesaran"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kawalan Tetingkap Pembesaran"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zum masuk"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kawalan ditambah.}other{# kawalan ditambah.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Dialih keluar"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Tambahkan <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Apabila anda menambahkan <xliff:g id="APPNAME">%s</xliff:g>, apl ini boleh menambahkan kawalan dan kandungan pada panel ini. Dalam sesetengah apl, anda boleh memilih kawalan yang muncul di sini."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Alih keluar kawalan untuk <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Digemari"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Digemari, kedudukan <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Dinyahgemari"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Lain-lain"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Tambahkan pada kawalan peranti"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Tambah"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Alih keluar"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Dicadangkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Peranti dikunci"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Tunjukkan dan kawal peranti daripada skrin kunci?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Anda boleh menambah kawalan untuk peranti luaran anda pada skrin kunci.\n\nApl peranti anda mungkin membenarkan anda mengawal sesetengah peranti tanpa membuka kunci telefon atau tablet anda.\n\nAnda boleh membuat perubahan pada bila-bila masa dalam Tetapan."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Kawal peranti daripada skrin kunci?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Anda boleh mengawal sesetengah peranti tanpa membuka kunci telefon atau tablet anda.\n\nApl peranti anda menentukan peranti yang boleh dikawal dengan cara ini."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Tidak perlu"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ya"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN mengandungi huruf atau simbol"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Tambah kawalan"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit kawalan"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tambahkan apl"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Alih keluar apl"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tambah output"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Kumpulan"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 peranti dipilih"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Sekurang-kurangnya satu peranti tersedia"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Tukar skrin sekarang"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Buka telefon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Tukar skrin?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Untuk peleraian lebih tinggi, gunakan kamera belakang"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Untuk peleraian lebih tinggi, balikkan telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Peranti boleh lipat dibuka"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Peranti boleh lipat diterbalikkan"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateri tinggal <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Tukar kepada profil kerja"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Tutup"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Tetapan skrin kunci"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi tidak tersedia"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera disekat"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dan mikrofon disekat"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon disekat"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mod keutamaan dihidupkan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/tiles_states_strings.xml b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
index f3dafa519140..07a8426feeb2 100644
--- a/packages/SystemUI/res/values-ms/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Mati"</item>
<item msgid="5966994759929723339">"Hidup"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Tidak tersedia"</item>
+ <item msgid="2478289035899842865">"Mati"</item>
+ <item msgid="5137565285664080143">"Hidup"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index b74dd93bf75f..8fa7be220720 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"မှားယွင်းသည့် ပင်နံပါတ်ကို နောက်တစ်ကြိမ်ထည့်သွင်းပါက သင်၏အလုပ်ပရိုဖိုင်နှင့် ၎င်း၏ဒေတာများကို ဖျက်လိုက်ပါမည်။"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"မှားယွင်းသည့် စကားဝှက်ကို နောက်တစ်ကြိမ်ထည့်သွင်းပါက သင်၏အလုပ်ပရိုဖိုင်နှင့် ၎င်း၏ ဒေတာများကို ဖျက်လိုက်ပါမည်။"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"လက်ဗွေအာရုံခံကိရိယာကို တို့ပါ"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"လက်ဗွေ သင်္ကေတ"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"မျက်နှာကို မမှတ်မိပါ။ လက်ဗွေကို အစားထိုးသုံးပါ။"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"အလုပ်သုံး လော့ခ်မျက်နှာပြင်"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ပိတ်ရန်"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"အလင်းတောက်ပမှု"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"အရောင်ပြောင်းပြန်ပြုလုပ်ရန်"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"အရောင် အမှန်ပြင်ခြင်း"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ဖောင့်အရွယ်အစား"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"အသုံးပြုသူများ စီမံရန်"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ပြီးပါပြီ"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ပိတ်ရန်"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"စခရင်ရိုက်ကူးမှု"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ခေါင်းစဉ် မရှိပါ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"အသင့်အနေအထား"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ဖောင့်အရွယ်အစား"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ချုံ့ရန်"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ချဲ့ရန်"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ဝင်းဒိုး ချဲ့ခြင်း"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ဝင်းဒိုး ထိန်းချုပ်မှုများ ချဲ့ခြင်း"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ဇူးမ်ဆွဲရန်"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{ထိန်းချုပ်ခလုတ် # ခု ထည့်ထားသည်။}other{ထိန်းချုပ်ခလုတ် # ခု ထည့်ထားသည်။}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"ဖယ်ရှားထားသည်"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ထည့်မလား။"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> ထည့်သောအခါ ၎င်းသည် ဤအကန့်တွင် သတ်မှတ်ချက်များနှင့် အကြောင်းအရာကို ထည့်နိုင်သည်။ အက်ပ်အချို့၌ မြင်ရမည့် သတ်မှတ်ချက်များကို ဤနေရာတွင် ရွေးနိုင်သည်။"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> အတွက် သတ်မှတ်ချက်များ ဖယ်ရှားမလား။"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"အကြိုက်ဆုံးတွင် ထည့်ထားသည်"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"အကြိုက်ဆုံးတွင် ထည့်ထားသည်၊ အဆင့် <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"အကြိုက်ဆုံးမှ ဖယ်ရှားထားသည်"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"အခြား"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"စက်ထိန်းစနစ်သို့ ထည့်ရန်"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ထည့်ရန်"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"ဖယ်ရှားရန်"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> က အကြံပြုထားသည်"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"စက်ကိုလော့ခ်ချထားသည်"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"လော့ခ်မျက်နှာပြင်တွင် စက်ပစ္စည်းများကြည့်ရှုပြီး ထိန်းချုပ်မလား။"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"လော့ခ်မျက်နှာပြင်တွင် ပြင်ပစက်များအတွက် ထိန်းချုပ်မှုများ ထည့်နိုင်သည်။\n\nသင့်စက်ပစ္စည်းအက်ပ်က အချို့စက်များကို ဖုန်း (သို့) တက်ဘလက် လော့ခ်ဖွင့်ရန်မလိုဘဲ သုံးခွင့်ပေးနိုင်သည်။\n\nဆက်တင်များ၌ အချိန်မရွေး ပြောင်းလဲပြင်ဆင်နိုင်သည်။"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"လော့ခ်မျက်နှာပြင်တွင် စက်ပစ္စည်းများ ထိန်းချုပ်မလား။"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"အချို့စက်များကို ဖုန်း (သို့) တက်ဘလက် လော့ခ်ဖွင့်ရန်မလိုဘဲ ထိန်းချုပ်နိုင်သည်။\n\nဤနည်းလမ်းအတိုင်း ထိန်းချုပ်နိုင်မည့်စက်များကို သင့်စက်ပစ္စည်းအက်ပ်က ဆုံးဖြတ်သည်။"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"မလိုပါ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yes"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ပင်နံပါတ်တွင် စာလုံး သို့မဟုတ် သင်္ကေတများပါဝင်သည်"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"ထိန်းချုပ်မှုများ ထည့်ရန်"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ထိန်းချုပ်မှုများ ပြင်ရန်"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"အက်ပ်ထည့်ရန်"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"အက်ပ်ဖယ်ရှားရန်"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"မီဒီယာအထွက်များ ထည့်ရန်"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"အုပ်စု"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"စက်ပစ္စည်း ၁ ခုကို ရွေးချယ်ထားသည်"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ထုတ်လွှင့်၍ မရပါ"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"သိမ်း၍မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"သိမ်း၍မရပါ။"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"အနည်းဆုံး အက္ခရာ ၄ လုံး သုံးရန်"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"အက္ခရာ ၁၆ လုံးအောက် သုံးရန်"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• အနည်းဆုံး စက်တစ်ခုသုံးနိုင်ရမည်"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ဖြတ်လမ်းလင့်ခ်ကို ထိပြီးဖိထားပါ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"မလုပ်တော့"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"စခရင်များ ယခုပြောင်းရန်"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ဖုန်းကို ဖြန့်လိုက်ပါ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"စခရင်များ ပြောင်းမလား။"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ပုံရိပ် ပိုမိုပြတ်သားစေရန် အနောက်ကင်မရာသုံးပါ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ပုံရိပ် ပိုမိုပြတ်သားစေရန် ဖုန်းကို တစ်ဖက်သို့ လှန်လိုက်ပါ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ခေါက်နိုင်သောစက်ကို ဖြန့်လိုက်သည်"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ခေါက်နိုင်သောစက်ကို တစ်ဘက်သို့ လှန်လိုက်သည်"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"ဘက်ထရီ <xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်သေးသည်"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"အလုပ်ပရိုဖိုင်သို့ ပြောင်းရန်"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ပိတ်ရန်"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"လော့ခ်မျက်နှာပြင် ဆက်တင်များ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi မရနိုင်ပါ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ကင်မရာကို ပိတ်ထားသည်"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ကင်မရာနှင့် မိုက်ခရိုဖုန်းကို ပိတ်ထားသည်"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"မိုက်ခရိုဖုန်းကို ပိတ်ထားသည်"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ဦးစားပေးမုဒ် ဖွင့်ထားသည်"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/tiles_states_strings.xml b/packages/SystemUI/res/values-my/tiles_states_strings.xml
index cadf00975048..fd375d4f3eb1 100644
--- a/packages/SystemUI/res/values-my/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-my/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"ပိတ်"</item>
<item msgid="5966994759929723339">"ဖွင့်"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"မရနိုင်ပါ"</item>
+ <item msgid="2478289035899842865">"ပိတ်"</item>
+ <item msgid="5137565285664080143">"ဖွင့်"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index af9cf7e24df4..a5b61034ea41 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Hvis du skriver inn feil PIN-kode på neste forsøk, slettes jobbprofilen din og tilknyttede data."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Hvis du skriver inn feil passord på neste forsøk, slettes jobbprofilen din og tilknyttede data."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Trykk på fingeravtrykkssensoren"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikon for fingeravtrykk"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansiktet gjenkjennes ikke. Bruk fingeravtrykk."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Varselskygge."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hurtiginnstillinger."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hurtiginnstillinger og varselpanelet"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låseskjerm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låseskjerm for arbeid"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Lukk"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Lysstyrke"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Fargeinvertering"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Fargekorrigering"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Skriftstørrelse"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Administrer brukere"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Ferdig"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Lukk"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"skjermopptak"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen tittel"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Ventemodus"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Skriftstørrelse"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Gjør mindre"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Gjør større"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Forstørringsvindu"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontroller for forstørringsvindu"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom inn"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontroll er lagt til.}other{# kontroller er lagt til.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Fjernet"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Vil du legge til <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Når du legger til <xliff:g id="APPNAME">%s</xliff:g>, kan den legge til kontroller og innhold i dette panelet. I noen apper kan du velge hvilke kontroller som vises her."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vil du fjerne kontrollene for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Favoritt"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favoritt, posisjon <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjernet som favoritt"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Annet"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Legg til i enhetsstyring"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Legg til"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Fjern"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Foreslått av <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Enheten er låst"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vil du se og kontrollere enheter fra låseskjermen?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Du kan legge til kontroller for de eksterne enhetene dine på låseskjermen.\n\nEnhetsappen kan la deg kontrollere noen enheter uten å låse opp telefonen eller nettbrettet.\n\nDu kan når som helst endre innstillingene."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vil du kontrollere enheter fra låseskjermen?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Du kan kontrollere enkelte enheter uten å låse opp telefonen eller nettbrettet.\n\nEnhetsappen fastslår hvilke enheter som kan kontrolleres på denne måten."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nei takk"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-koden inneholder bokstaver eller symboler"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Legg til kontroller"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Endre kontroller"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Legg til app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Fjern appen"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Legg til utenheter"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 enhet er valgt"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Kan ikke kringkaste"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Bruk minst 4 tegn"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Bruk færre enn 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• minst én enhet er tilgjengelig"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Bytt skjerm nå"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Brett ut telefonen"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vil du bytte skjerm?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Bruk baksidekameraet for å få høyere oppløsning"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Brett ut telefonen for å få høyere oppløsning"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En sammenleggbar enhet blir brettet ut"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"En sammenleggbar enhet blir snudd"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batteri gjenstår"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Bytt til jobbprofilen"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Lukk"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Innstillinger for låseskjermen"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi er ikke tilgjengelig"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameraet er blokkert"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameraet og mikrofonen er blokkert"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen er blokkert"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteringsmodus er på"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/tiles_states_strings.xml b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
index b465617aa6fd..e4a811941b2a 100644
--- a/packages/SystemUI/res/values-nb/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Av"</item>
<item msgid="5966994759929723339">"På"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Utilgjengelig"</item>
+ <item msgid="2478289035899842865">"Av"</item>
+ <item msgid="5137565285664080143">"På"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index ff017ab166cd..c28b5b09a675 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"तपाईंले अर्को पटक पनि गलत PIN प्रविष्टि गर्नुभयो भने तपाईंको कार्य प्रोफाइल र त्यहाँको डेटा मेटाइने छ।"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"तपाईंले अर्को पटक पनि गलत पासवर्ड प्रविष्टि गर्नुभयो भने तपाईंको कार्य प्रोफाइल र त्यहाँको डेटा मेटाइने छ।"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"फिंगरप्रिन्ट सेन्सरमा छुनुहोस्‌"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"फिंगरप्रिन्ट जनाउने आइकन"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"अनुहार पहिचान गर्न सकिएन। बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्।"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"कार्य प्रोफाइलको लक स्क्रिन"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"बन्द गर्नुहोस्"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"उज्यालपन"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"कलर इन्भर्सन"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"कलर करेक्सन"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"फन्टको आकार"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"प्रयोगकर्ताहरू व्यवस्थित गर्नुहोस्"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"भयो"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"बन्द गर्नुहोस्"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"स्क्रिन रेकर्डिङ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक छैन"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"स्ट्यान्डबाई"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"फन्टको आकार"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"अझ सानो बनाउनुहोस्"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"अझ ठुलो बनाउनुहोस्"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"म्याग्निफिकेसन विन्डो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"म्याग्निफिकेसन विन्डोका नियन्त्रणहरू"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"जुम इन गर्नुहोस्"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# कन्ट्रोल हालियो।}other{# वटा कन्ट्रोल हालियो।}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"हटाइएको"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> हाल्ने हो?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"तपाईंले <xliff:g id="APPNAME">%s</xliff:g> हाल्नुभयो भने यसले यो प्यानलमा सेटिङ र सामग्री हाल्न सक्छ। तपाईं केही एपहरूमा यहाँ कुन कुन सेटिङ देखाउने भन्ने कुरा छनौट गर्न सक्नुहुन्छ।"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> का सेटिङ हटाउने हो?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"मनपराइएको"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"मन पराइएका कुराहरूको <xliff:g id="NUMBER">%d</xliff:g> औँ स्थानमा"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"मन पर्ने कुराहरूको सूचीमा नराखिएको"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"अन्य"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"डिभाइस नियन्त्रण गर्ने विजेटहरूको सूचीमा थप्नुहोस्"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"थप्नुहोस्"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"हटाउनुहोस्"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ले सिफारिस गरेको"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"यन्त्र लक गरिएको छ"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"लक स्क्रिनमै डिभाइसहरू देखाउने र लक स्क्रिनबाटै ती डिभाइसहरू नियन्त्रण गर्ने हो?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"तपाईं आफ्ना बाह्य डिभाइसहरूका कन्ट्रोलहरू लक स्क्रिनमा हाल्न सक्नुहुन्छ।\n\nतपाईंको डिभाइसको एपले तपाईंलाई आफ्नो फोन वा ट्याब्लेट अनलक नगरिकनै केही डिभाइसहरू नियन्त्रण गर्ने अनुमति दिन सक्छ।\n\nतपाईं जुनसुकै बेला सेटिङमा गई यी कुराहरू बदल्न सक्नुहुन्छ।"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"लक स्क्रिनबाटै डिभाइसहरू नियन्त्रण गर्ने हो?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"तपाईं आफ्नो फोन वा ट्याब्लेट अनलक नगरिकनै केही डिभाइसहरू नियन्त्रण गर्न सक्नुहुन्छ।\n\nतपाईंको डिभाइस एपले यस तरिकाले कुन कुन डिभाइस नियन्त्रण गर्न सकिन्छ भन्ने कुरा निर्धारण गर्छ।"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"पर्दैन"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"अँ"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN मा अक्षर वा चिन्हहरू समाविष्ट हुन्छन्"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"कन्ट्रोल थप्नुहोस्"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"कन्ट्रोल सम्पादन गर्नुहोस्"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"एप हाल्नुहोस्"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"यो एप हटाउनुहोस्"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट यन्त्रहरू थप्नुहोस्"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"समूह"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"१ यन्त्र चयन गरियो"</string>
@@ -961,7 +962,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"इन्टरनेटमा कनेक्ट गरिएको छ"</string>
- <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"केही समयका लागि मोबाइल डेटामा कनेक्ट गरिएको छ"</string>
+ <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"यसमा केही समयका लागि कनेक्ट गरिएको हो"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"इन्टरनेट राम्री चलेको छैन"</string>
<string name="mobile_data_off_summary" msgid="3663995422004150567">"मोबाइल डेटा स्वतः कनेक्ट हुँदैन"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"इन्टरनेट छैन"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• कम्तीमा एउटा डिभाइस उपलब्ध छ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"सर्टकट थिचिराख्नुहोस्"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द गर्नुहोस्"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"अहिले नै स्क्रिन बदल्नुहोस्"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"फोन अनफोल्ड गर्नुहोस्"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"स्क्रिनहरू बदल्ने हो?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"उच्च रिजोल्युसनको सेल्फी खिच्न पछाडिको क्यामेरा प्रयोग गर्नुहोस्"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"उच्च रिजोल्युसनको सेल्फी खिच्न फोन फ्लिप गर्नुहोस्"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फोल्ड गर्न मिल्ने डिभाइस अनफोल्ड गरेको देखाइएको एनिमेसन"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फोल्ड गर्न मिल्ने डिभाइस यताउता पल्टाएर देखाइएको एनिमेसन"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ब्याट्री बाँकी छ"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"कार्य प्रोफाइल प्रयोग गर्नुहोस्"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"बन्द गर्नुहोस्"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"लक स्क्रिनसम्बन्धी सेटिङ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi उपलब्ध छैन"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"क्यामेरा ब्लक गरिएको छ"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"क्यामेरा र माइक्रोफोन ब्लक गरिएको छ"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"माइक्रोफोन ब्लक गरिएको छ"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राथमिकता मोड अन छ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/tiles_states_strings.xml b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
index bbdf72a3fa44..5cf91e533494 100644
--- a/packages/SystemUI/res/values-ne/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"अफ"</item>
<item msgid="5966994759929723339">"अन"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"उपलब्ध छैन"</item>
+ <item msgid="2478289035899842865">"अफ छ"</item>
+ <item msgid="5137565285664080143">"अन छ"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index a368fcf90cab..139bb8d35b4f 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Als je bij de volgende poging een onjuiste pincode opgeeft, worden je werkprofiel en de bijbehorende gegevens verwijderd."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Als je bij de volgende poging een onjuist wachtwoord opgeeft, worden je werkprofiel en de bijbehorende gegevens verwijderd."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Raak de vingerafdruksensor aan"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Vingerafdrukpictogram"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Gezicht niet herkend. Gebruik je vingerafdruk."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meldingenpaneel."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snelle instellingen."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Snelle instellingen en meldingenpaneel."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Vergrendelscherm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Vergrendelscherm voor werk"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Sluiten"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Helderheid"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Kleurinversie"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Kleurcorrectie"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Lettergrootte"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gebruikers beheren"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Klaar"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Sluiten"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"schermopname"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Geen titel"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stand-by"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Lettergrootte"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Verkleinen"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Vergroten"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrotingsvenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Bediening van vergrotingsvenster"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Inzoomen"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# bedieningselement toegevoegd.}other{# bedieningselementen toegevoegd.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Verwijderd"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> toevoegen?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Als je <xliff:g id="APPNAME">%s</xliff:g> toevoegt, kan deze app bedieningselementen en content aan dit deelvenster toevoegen. In sommige apps kun je kiezen welke bedieningselementen hier worden getoond."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Bedieningselementen voor <xliff:g id="APPNAME">%s</xliff:g> verwijderen?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Gemarkeerd als favoriet"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Gemarkeerd als favoriet, positie <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Verwijderd als favoriet"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Overig"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Toevoegen aan apparaatbediening"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Toevoegen"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Verwijderen"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Voorgesteld door <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Apparaat vergrendeld"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Apparaten tonen en bedienen via het vergrendelscherm?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Je kunt bedieningselementen voor je externe apparaten toevoegen aan het vergrendelscherm.\n\nMet je apparaat-app kun je misschien bepaalde apparaten bedienen zonder je telefoon of tablet te ontgrendelen.\n\nJe kunt op elk moment wijzigingen aanbrengen via Instellingen."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Apparaten bedienen via vergrendelscherm?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Je kunt bepaalde apparaten bedienen zonder je telefoon of tablet te ontgrendelen.\n\nJe apparaat-app bepaalt welke apparaten op deze manier kunnen worden bediend."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nee, bedankt"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Pincode bevat letters of symbolen"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Bedieningselementen toevoegen"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Bedieningselementen bewerken"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"App toevoegen"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"App verwijderen"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Uitvoer toevoegen"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Groep"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Eén apparaat geselecteerd"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Er is ten minste één apparaat beschikbaar"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Wissel nu van scherm"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Telefoon openklappen"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Van scherm wisselen?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Gebruik de camera aan de achterzijde voor een hogere resolutie"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Draai de telefoon om voor een hogere resolutie"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Opvouwbaar apparaat wordt uitgevouwen"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Opvouwbaar apparaat wordt gedraaid"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Nog <xliff:g id="PERCENTAGE">%s</xliff:g> batterijlading"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Overschakelen naar werkprofiel"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Sluiten"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Instellingen vergrendelscherm"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi niet beschikbaar"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera geblokkeerd"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera en microfoon geblokkeerd"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfoon geblokkeerd"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteitsmodus aan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/tiles_states_strings.xml b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
index b51dc653912b..592ecf5b69d6 100644
--- a/packages/SystemUI/res/values-nl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Uit"</item>
<item msgid="5966994759929723339">"Aan"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Niet beschikbaar"</item>
+ <item msgid="2478289035899842865">"Uit"</item>
+ <item msgid="5137565285664080143">"Aan"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 0fd1d1d86556..33d1865c180c 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ PIN ଲେଖିଲେ, ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଏବଂ ଏହାର ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ ପାସୱାର୍ଡ ଲେଖିଲେ, ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଓ ଏହାର ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ଟିପଚିହ୍ନ ସେନସର୍‌କୁ ଛୁଅଁନ୍ତୁ"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ଫେସ୍ ଚିହ୍ନଟ କରିହେବ ନାହିଁ। ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"ୱର୍କ ଲକ୍‍ ସ୍କ୍ରୀନ୍‍"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ବନ୍ଦ କରନ୍ତୁ"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ଉଜ୍ଜ୍ୱଳତା"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ରଙ୍ଗ ଇନଭାର୍ସନ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ରଙ୍ଗ ସଂଶୋଧନ"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ଫଣ୍ଟର ଆକାର"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ୟୁଜରମାନଙ୍କୁ ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ହୋଇଗଲା"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ବନ୍ଦ କରନ୍ତୁ"</string>
@@ -400,8 +399,8 @@
<string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ବିକଳ୍ପ ଦ୍ୱାରା ବିଜ୍ଞପ୍ତି ପଜ୍‍ ହୋଇଛି"</string>
<string name="media_projection_action_text" msgid="3634906766918186440">"ବର୍ତ୍ତମାନ ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string>
- <string name="no_unseen_notif_text" msgid="395512586119868682">"କୌଣସି ନୂଆ ବିଜ୍ଞପ୍ତି ନାହିଁ"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ପୁରୁଣା ବିଜ୍ଞପ୍ତି ଦେଖିବାକୁ ଅନଲକ କରନ୍ତୁ"</string>
+ <string name="no_unseen_notif_text" msgid="395512586119868682">"କୌଣସି ନୂଆ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ନାହିଁ"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ପୁରୁଣା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଦେଖିବାକୁ ଅନଲକ କରନ୍ତୁ"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ଏହି ଡିଭାଇସ୍ ଆପଣଙ୍କ ବାପାମାଙ୍କ ଦ୍ୱାରା ପରିଚାଳିତ"</string>
<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>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ସ୍କ୍ରିନ ରେକର୍ଡିଂ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"କୌଣସି ଶୀର୍ଷକ ନାହିଁ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ଷ୍ଟାଣ୍ଡବାଏ"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ଫଣ୍ଟର ଆକାର"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ଛୋଟ କରନ୍ତୁ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ବହୁତ ବଡ଼ କରନ୍ତୁ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ଜୁମ୍ ଇନ୍ କରନ୍ତୁ"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{#ଟି ନିୟନ୍ତ୍ରଣ ଯୋଗ କରାଯାଇଛି।}other{#ଟି ନିୟନ୍ତ୍ରଣ ଯୋଗ କରାଯାଇଛି।}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"କାଢ଼ି ଦିଆଯାଇଛି"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>କୁ ଯୋଗ କରିବେ?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"ଯେତେବେଳେ ଆପଣ <xliff:g id="APPNAME">%s</xliff:g>କୁ ଯୋଗ କରନ୍ତି, ସେତେବେଳେ ଏହି ପେନେଲରେ ଏହା ନିୟନ୍ତ୍ରଣ ଏବଂ ବିଷୟବସ୍ତୁ ଯୋଗ କରିପାରିବ। କିଛି ଆପ୍ସରେ, ଏଠାରେ କେଉଁ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଦେଖାଯିବ ତାହା ଆପଣ ବାଛିପାରିବେ।"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> ପାଇଁ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ କାଢ଼ି ଦେବେ?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"ପସନ୍ଦ କରାଯାଇଛି"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"ପସନ୍ଦ କରାଯାଇଛି, ସ୍ଥିତି <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ନାପସନ୍ଦ କରାଯାଇଛି"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ଅନ୍ୟ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ଡିଭାଇସ୍ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକରେ ଯୋଗ କରନ୍ତୁ"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ଯୋଗ କରନ୍ତୁ"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"କାଢ଼ି ଦିଅନ୍ତୁ"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ଦ୍ଵାରା ପ୍ରସ୍ତାବିତ"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"ଡିଭାଇସ୍ ଲକ୍ ହୋଇଯାଇଛି"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ଲକ ସ୍କ୍ରିନରୁ ଡିଭାଇସଗୁଡ଼ିକୁ ଦେଖାଇବେ ଏବଂ ନିୟନ୍ତ୍ରଣ କରିବେ?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ଆପଣ ଲକ ସ୍କ୍ରିନରେ ଆପଣଙ୍କ ଏକ୍ସଟର୍ନଲ ଡିଭାଇସଗୁଡ଼ିକ ପାଇଁ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଯୋଗ କରିପାରିବେ।\n\nଆପଣଙ୍କ ଫୋନ କିମ୍ବା ଟାବଲେଟକୁ ଅନଲକ ନକରି କିଛି ଡିଭାଇସକୁ ନିୟନ୍ତ୍ରଣ କରିବା ପାଇଁ ଆପଣଙ୍କ ଡିଭାଇସର ଆପ ଆପଣଙ୍କୁ ଅନୁମତି ଦେଇପାରେ।\n\nଆପଣ ଯେ କୌଣସି ସମୟରେ ସେଟିଂସରେ ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ଲକ ସ୍କ୍ରିନରୁ ଡିଭାଇସଗୁଡ଼ିକୁ ନିୟନ୍ତ୍ରଣ କରିବେ?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"ଆପଣ ଆପଣଙ୍କ ଫୋନ କିମ୍ବା ଟାବଲେଟକୁ ଅନଲକ ନକରି କିଛି ଡିଭାଇସକୁ ନିୟନ୍ତ୍ରଣ କରିପାରିବେ।\n\nଏହି ଉପାୟରେ କେଉଁ ଡିଭାଇସଗୁଡ଼ିକୁ ନିୟନ୍ତ୍ରଣ କରାଯାଇପାରିବ ତାହା ଆପଣଙ୍କ ଡିଭାଇସର ଆପ ସ୍ଥିର କରେ।"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ନା, ଧନ୍ୟବାଦ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ହଁ"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PINରେ ଅକ୍ଷର କିମ୍ୱା ପ୍ରତୀକଗୁଡ଼ିକ ଥାଏ"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଯୋଗ କରନ୍ତୁ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଏଡିଟ କରନ୍ତୁ"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"ଆପ ଯୋଗ କରନ୍ତୁ"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"ଆପକୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"ଆଉଟପୁଟ୍ ଯୋଗ କରନ୍ତୁ"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"ଗୋଷ୍ଠୀ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1ଟି ଡିଭାଇସ୍ ଚୟନ କରାଯାଇଛି"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ଅତିକମରେ ଗୋଟିଏ ଡିଭାଇସ ଉପଲବ୍ଧ ଅଛି"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ସର୍ଟକଟକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ବାତିଲ କରନ୍ତୁ"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ବର୍ତ୍ତମାନ ସ୍କ୍ରିନ ସ୍ୱିଚ କରନ୍ତୁ"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ଫୋନକୁ ଅନଫୋଲ୍ଡ କରନ୍ତୁ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ସ୍କ୍ରିନ ସ୍ୱିଚ କରିବେ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ଉଚ୍ଚ ରିଜୋଲ୍ୟୁସନ ପାଇଁ ପଛ କେମେରା ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ଉଚ୍ଚ ରିଜୋଲ୍ୟୁସନ ପାଇଁ ଫୋନକୁ ଫ୍ଲିପ କରନ୍ତୁ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ଫୋଲ୍ଡ କରାଯାଇପାରୁଥିବା ଡିଭାଇସକୁ ଅନଫୋଲ୍ଡ କରାଯାଉଛି"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ଫୋଲ୍ଡ କରାଯାଇପାରୁଥିବା ଡିଭାଇସକୁ ଫ୍ଲିପ କରାଯାଉଛି"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ବେଟେରୀ ଚାର୍ଜ ବାକି ଅଛି"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ୱାର୍କ ପ୍ରୋଫାଇଲକୁ ସ୍ୱିଚ କରନ୍ତୁ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ଲକ ସ୍କ୍ରିନ ସେଟିଂସ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ୱାଇ-ଫାଇ ଉପଲବ୍ଧ ନାହିଁ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"କେମେରାକୁ ବ୍ଲକ କରାଯାଇଛି"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"କେମେରା ଏବଂ ମାଇକ୍ରୋଫୋନକୁ ବ୍ଲକ କରାଯାଇଛି"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ମାଇକ୍ରୋଫୋନକୁ ବ୍ଲକ କରାଯାଇଛି"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ପ୍ରାୟୋରିଟି ମୋଡ ଚାଲୁ ଅଛି"</string>
</resources>
diff --git a/packages/SystemUI/res/values-or/tiles_states_strings.xml b/packages/SystemUI/res/values-or/tiles_states_strings.xml
index 5e4b730f6144..d362c65fa971 100644
--- a/packages/SystemUI/res/values-or/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-or/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"ବନ୍ଦ ଅଛି"</item>
<item msgid="5966994759929723339">"ଚାଲୁ ଅଛି"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ଅନୁପଲବ୍ଧ"</item>
+ <item msgid="2478289035899842865">"ବନ୍ଦ ଅଛି"</item>
+ <item msgid="5137565285664080143">"ଚାଲୁ ଅଛି"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 28c6b314a41d..b81ca653e28b 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪਿੰਨ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਇਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਇਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਪ੍ਰਤੀਕ"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ਚਿਹਰਾ ਨਹੀਂ ਪਛਾਣ ਸਕਦੇ। ਇਸਦੀ ਬਜਾਏ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ।"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"ਕਾਰਜ-ਸਥਾਨ ਲਾਕ ਸਕ੍ਰੀਨ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ਬੰਦ ਕਰੋ"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ਚਮਕ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ਰੰਗ ਪਲਟਨਾ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ਰੰਗ ਸੁਧਾਈ"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ਫੌਂਟ ਦਾ ਆਕਾਰ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ਵਰਤੋਂਕਾਰਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ਹੋ ਗਿਆ"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ਬੰਦ ਕਰੋ"</string>
@@ -400,7 +399,7 @@
<string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਵੱਲੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਰੋਕਿਆ ਗਿਆ"</string>
<string name="media_projection_action_text" msgid="3634906766918186440">"ਹੁਣੇ ਸ਼ੁਰੂ ਕਰੋ"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"ਕੋਈ ਸੂਚਨਾਵਾਂ ਨਹੀਂ"</string>
- <string name="no_unseen_notif_text" msgid="395512586119868682">"ਕੋਈ ਨਵੀਂ ਸੂਚਨਾ ਨਹੀਂ"</string>
+ <string name="no_unseen_notif_text" msgid="395512586119868682">"ਕੋਈ ਨਵੀਂ ਸੂਚਨਾ ਨਹੀਂ ਹੈ"</string>
<string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ਪੁਰਾਣੀਆਂ ਸੂਚਨਾਵਾਂ ਦੇਖਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਕੋਲ ਇਸ ਡੀਵਾਈਸ ਦੀ ਮਲਕੀਅਤ ਹੈ ਅਤੇ ਇਹ ਨੈੱਟਵਰਕ ਟਰੈਫ਼ਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ਕੋਈ ਸਿਰਲੇਖ ਨਹੀਂ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ਸਟੈਂਡਬਾਈ"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ਫ਼ੌਂਟ ਦਾ ਆਕਾਰ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ਛੋਟਾ ਕਰੋ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ਵੱਡਾ ਕਰੋ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ਵੱਡਦਰਸ਼ੀਕਰਨ Window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ਵੱਡਦਰਸ਼ੀਕਰਨ Window ਦੇ ਕੰਟਰੋਲ"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ਜ਼ੂਮ ਵਧਾਓ"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ।}one{# ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ।}other{# ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕੀਤੇ ਗਏ।}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"ਹਟਾਇਆ ਗਿਆ"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"ਕੀ <xliff:g id="APPNAME">%s</xliff:g> ਸ਼ਾਮਲ ਕਰਨਾ ਹੈ?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"ਜਦੋਂ ਤੁਸੀਂ <xliff:g id="APPNAME">%s</xliff:g> ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਇਹ ਇਸ ਪੈਨਲ ਵਿੱਚ ਕੰਟਰੋਲਾਂ ਅਤੇ ਸਮੱਗਰੀ ਨੂੰ ਸ਼ਾਮਲ ਕਰ ਸਕਦੀ ਹੈ। ਕੁਝ ਐਪਾਂ ਲਈ, ਤੁਸੀਂ ਇਹ ਚੁਣ ਸਕਦੇ ਹੋ ਕਿ ਇੱਥੇ ਕਿਹੜੇ ਕੰਟਰੋਲ ਦਿਸਣ।"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"ਕੀ <xliff:g id="APPNAME">%s</xliff:g> ਲਈ ਕੰਟਰੋਲਾਂ ਨੂੰ ਹਟਾਉਣਾ ਹੈ?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"ਮਨਪਸੰਦ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"ਮਨਪਸੰਦ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ, ਸਥਾਨ <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ਮਨਪਸੰਦ ਵਿੱਚੋਂ ਹਟਾਇਆ ਗਿਆ"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ਹੋਰ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ਡੀਵਾਈਸ ਕੰਟਰੋਲਾਂ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ਸ਼ਾਮਲ ਕਰੋ"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"ਹਟਾਓ"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ਵੱਲੋਂ ਸੁਝਾਇਆ ਗਿਆ"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"ਡੀਵਾਈਸ ਲਾਕ ਹੈ"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ਕੀ ਲਾਕ ਸਕ੍ਰੀਨ ਤੋਂ ਡੀਵਾਈਸਾਂ ਨੂੰ ਦੇਖਣਾ ਅਤੇ ਕੰਟਰੋਲ ਕਰਨਾ ਹੈ?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ਤੁਸੀਂ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਆਪਣੇ ਬਾਹਰੀ ਡੀਵਾਈਸਾਂ ਲਈ ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰ ਸਕਦੇ ਹੋ।\n\nਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਮੌਜੂਦ ਐਪ ਤੁਹਾਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਜਾਂ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕੀਤੇ ਬਿਨਾਂ ਕੁਝ ਡੀਵਾਈਸਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰਨ ਦੇ ਸਕਦੀ ਹੈ।\n\nਤੁਸੀਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਕਿਸੇ ਵੇਲੇ ਵੀ ਤਬਦੀਲੀਆਂ ਕਰ ਸਕਦੇ ਹੋ।"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ਕੀ ਲਾਕ ਸਕ੍ਰੀਨ ਤੋਂ ਡੀਵਾਈਸਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰਨਾ ਹੈ?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"ਤੁਸੀਂ ਆਪਣੇ ਫ਼ੋਨ ਜਾਂ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕੀਤੇ ਬਿਨਾਂ ਕੁਝ ਡੀਵਾਈਸਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰ ਸਕਦੇ ਹੋ।\n\nਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਮੌਜੂਦ ਐਪ ਇਹ ਨਿਰਧਾਰਿਤ ਕਰਦੀ ਹੈ ਕਿ ਇਸ ਤਰੀਕੇ ਨਾਲ ਕਿਹੜੇ ਡੀਵਾਈਸਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ਹਾਂ"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ਪਿੰਨ ਵਿੱਚ ਅੱਖਰ ਜਾਂ ਚਿੰਨ੍ਹ ਸ਼ਾਮਲ ਹਨ"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ਕੰਟਰੋਲਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"ਐਪ ਸ਼ਾਮਲ ਕਰੋ"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"ਐਪ ਹਟਾਓ"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"ਆਊਟਪੁੱਟ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"ਗਰੁੱਪ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ਡੀਵਾਈਸ ਨੂੰ ਚੁਣਿਆ ਗਿਆ"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ਘੱਟੋ-ਘੱਟ ਇੱਕ ਡੀਵਾਈਸ ਉਪਲਬਧ ਹੈ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਸਪਰਸ਼ ਕਰ ਕੇ ਰੱਖੋ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ਰੱਦ ਕਰੋ"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ਹੁਣ ਸਕ੍ਰੀਨਾਂ ਨੂੰ ਸਵਿੱਚ ਕਰੋ"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ਫ਼ੋਨ ਨੂੰ ਖੋਲ੍ਹੋ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ਕੀ ਸਕ੍ਰੀਨਾਂ ਨੂੰ ਸਵਿੱਚ ਕਰਨਾ ਹੈ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ਉੱਚ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਲਈ, ਪਿਛਲਾ ਕੈਮਰਾ ਵਰਤੋ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ਉੱਚ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਲਈ, ਫ਼ੋਨ ਨੂੰ ਫਲਿੱਪ ਕਰੋ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ਮੋੜਨਯੋਗ ਡੀਵਾਈਸ ਨੂੰ ਖੋਲ੍ਹਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ਮੋੜਨਯੋਗ ਡੀਵਾਈਸ ਨੂੰ ਆਲੇ-ਦੁਆਲੇ ਫਲਿੱਪ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬੈਟਰੀ ਬਾਕੀ"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ \'ਤੇ ਜਾਓ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ਬੰਦ ਕਰੋ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ਵਾਈ-ਫਾਈ ਉਪਲਬਧ ਨਹੀਂ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ਕੈਮਰਾ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ਕੈਮਰਾ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤੇ ਗਏ"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ਤਰਜੀਹ ਮੋਡ ਚਾਲੂ ਹੈ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/tiles_states_strings.xml b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
index 5628a3167b87..f249afb72b6d 100644
--- a/packages/SystemUI/res/values-pa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"ਬੰਦ"</item>
<item msgid="5966994759929723339">"ਚਾਲੂ"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ਉਪਲਬਧ ਨਹੀਂ"</item>
+ <item msgid="2478289035899842865">"ਬੰਦ"</item>
+ <item msgid="5137565285664080143">"ਚਾਲੂ"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index ed0d257889b4..36e7a84256c2 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jeśli następnym razem podasz nieprawidłowy kod PIN, profil służbowy oraz powiązane z nim dane zostaną usunięte."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Jeśli następnym razem podasz nieprawidłowe hasło, profil służbowy oraz powiązane z nim dane zostaną usunięte."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotknij czytnika linii papilarnych"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona odcisku palca"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nie rozpoznaję twarzy. Użyj odcisku palca."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obszar powiadomień."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Szybkie ustawienia."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Szybkie ustawienia i obszar powiadomień."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ekran blokady."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekran blokady wyświetlany podczas działania"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zamknij"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Jasność"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Odwrócenie kolorów"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekcja kolorów"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Rozmiar czcionki"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Zarządzaj użytkownikami"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Gotowe"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zamknij"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"nagrywanie ekranu"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez tytułu"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Tryb gotowości"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Rozmiar czcionki"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Pomniejsz"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Powiększ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Okno powiększenia"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Elementy sterujące okna powiększenia"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Powiększ"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Dodano # element sterujący.}few{Dodano # elementy sterujące.}many{Dodano # elementów sterujących.}other{Dodano # elementu sterującego.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Usunięto"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Dodać aplikację <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Gdy dodasz aplikację <xliff:g id="APPNAME">%s</xliff:g>, będzie ona mogła dodawać elementy sterujące i treści do tego panelu. W niektórych aplikacjach można wybrać elementy sterujące, które się tu pojawią."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Usunąć elementy sterujące aplikacji <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano do ulubionych"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano do ulubionych, pozycja <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Usunięto z ulubionych"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Inne"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Dodaj do sterowania urządzeniami"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Usuń"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Sugestia: <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Urządzenie zablokowane"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Pokazywać urządzenia i umożliwiać sterowanie nimi na ekranie blokady?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Możesz dodać do ekranu blokady elementy sterujące dotyczące urządzeń zewnętrznych.\n\nMożesz mieć możliwość sterowania niektórymi urządzeniami za pomocą aplikacji na telefonie lub tablecie bez odblokowywania tych urządzeń.\n\nW dowolnej chwili możesz wprowadzić zmiany w Ustawieniach."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Sterować urządzeniami na ekranie blokady?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Możesz sterować niektórymi urządzeniami bez odblokowywania telefonu lub tabletu.\n\nTo, którymi urządzeniami możesz sterować w ten sposób, określa aplikacja na urządzeniu."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nie, dziękuję"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Tak"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Kod PIN zawiera litery lub symbole"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Dodaj elementy sterujące"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edytuj elementy sterujące"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikację"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Usuń aplikację"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodaj urządzenia wyjściowe"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Wybrano 1 urządzenie"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Dostępne jest co najmniej 1 urządzenie."</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Przełącz ekrany teraz"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Otwieranie telefonu"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Przełączyć ekrany?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Użyj tylnego aparatu, aby uzyskać wyższą rozdzielczość"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Odwróć telefon, aby uzyskać wyższą rozdzielczość"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Składane urządzenie jest rozkładane"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Składane urządzenie jest obracane"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g> baterii"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Przełącz na profil służbowy"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zamknij"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Ustawienia ekranu blokady"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Sieć Wi-Fi jest niedostępna"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera jest zablokowana"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon są zablokowane"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon jest zablokowany"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Tryb priorytetowy jest włączony"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
index c32aa1a69a43..c73cbed76946 100644
--- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Wyłączono"</item>
<item msgid="5966994759929723339">"Włączono"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Brak dostępu"</item>
+ <item msgid="2478289035899842865">"Wyłączono"</item>
+ <item msgid="5137565285664080143">"Włączono"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 1b9e0150ce26..c778371a8177 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Se você informar um PIN incorreto na próxima tentativa, seu perfil de trabalho e os dados dele serão excluídos."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Se você informar uma senha incorreta na próxima tentativa, seu perfil de trabalho e os dados dele serão excluídos."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toque no sensor de impressão digital"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ícone de impressão digital"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Não foi possível reconhecer o rosto Use a impressão digital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Aba de notificações."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configurações rápidas."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configurações rápidas e aba de notificações."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Tela de bloqueio."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Tela de bloqueio de trabalho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brilho"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversão de cores"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correção de cor"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamanho da fonte"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gerenciar usuários"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Concluído"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Fechar"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie para conferir as notificações antigas"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie p/ acessar notificações antigas"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Sua organização é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"A organização <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"gravação de tela"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Em espera"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamanho da fonte"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Diminuir"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controles da janela de ampliação"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumentar zoom"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}many{# de controles adicionados.}other{# controles adicionados.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Adicionar o app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Quando você adiciona o app <xliff:g id="APPNAME">%s</xliff:g>, ele pode incluir controles e conteúdo neste painel. Em alguns casos, é possível escolher quais controles aparecem aqui."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remover controles do app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outro"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Adicionar aos controles do dispositivo"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Remover"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloq."</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Mostrar e controlar dispositivos na tela de bloqueio?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Você pode adicionar à tela de bloqueio controles para dispositivos externos.\n\nO app do dispositivo pode permitir que você controle alguns dispositivos sem desbloquear o smartphone ou tablet.\n\nÉ possível fazer mudanças a qualquer momento nas Configurações."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Controlar dispositivos na tela de bloqueio?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"É possível controle alguns dispositivos sem desbloquear o smartphone ou tablet.\n\nO app do dispositivo determina quais dispositivos podem ser controlados dessa maneira."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Agora não"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sim"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contém letras ou símbolos"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controles"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adicionar app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Remover o app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicionar saídas"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Não foi possível fazer a transmissão"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use pelo menos 4 caracteres"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use menos de 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Pelo menos um dispositivo está disponível"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Trocar de tela agora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Abra o smartphone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Trocar de tela?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para uma resolução maior, use a câmera traseira"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para uma resolução maior, vire o smartphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável sendo aberto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável sendo virado"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateria restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Alternar para o perfil de trabalho"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Configurações de tela de bloqueio"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Câmara bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Câmera e microfone bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfone bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo de prioridade ativado"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
index cea45323069f..28c07f40b6b9 100644
--- a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Desativado"</item>
<item msgid="5966994759929723339">"Ativado"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Indisponível"</item>
+ <item msgid="2478289035899842865">"Desativado"</item>
+ <item msgid="5137565285664080143">"Ativado"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 22ddebfc0317..b0d9d39a5df6 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -150,8 +150,8 @@
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Prima ícone de desbloqueio para continuar"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string>
- <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utilizar padrão"</string>
- <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Utilizar palavra-passe"</string>
+ <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrão"</string>
+ <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Usar palavra-passe"</string>
<string name="biometric_dialog_wrong_pin" msgid="1878539073972762803">"PIN incorreto."</string>
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Padrão incorreto."</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Palavra-passe incorreta."</string>
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Se introduzir um PIN incorreto na tentativa seguinte, o seu perfil de trabalho e os respetivos dados serão eliminados."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Se introduzir uma palavra-passe incorreta na tentativa seguinte, o seu perfil de trabalho e os respetivos dados serão eliminados."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toque no sensor de impressões digitais."</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ícone de impressão digital"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Impos. reconh. rosto. Utilize a impressão digital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Painel de notificações."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Definições rápidas."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Definições rápidas e painel de notificações."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ecrã de bloqueio."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ecrã de bloqueio de trabalho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
@@ -695,7 +695,7 @@
<string name="tuner_lock_screen" msgid="2267383813241144544">"Ecrã de bloqueio"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telem. deslig. devido ao calor"</string>
<string name="thermal_shutdown_message" msgid="6142269839066172984">"O seu telemóvel já está a funcionar normalmente.\nToque para obter mais informações."</string>
- <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"O telemóvel estava muito quente, por isso desligou-se para arrefecer. Agora funciona normalmente.\n\nO telemóvel pode sobreaquecer se:\n • Utilizar aplicações que utilizam mais recursos (jogos, vídeo ou aplicações de navegação)\n • Transferir ou carregar ficheiros grandes\n • Utilizar em altas temperaturas"</string>
+ <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"O telemóvel estava muito quente, por isso desligou-se para arrefecer. Agora funciona normalmente.\n\nO telemóvel pode sobreaquecer se:\n • Usar aplicações que utilizam mais recursos (jogos, vídeo ou aplicações de navegação)\n • Transferir ou carregar ficheiros grandes\n • Usar em altas temperaturas"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Veja os passos de manutenção"</string>
<string name="high_temp_title" msgid="2218333576838496100">"O telemóvel está a aquecer"</string>
<string name="high_temp_notif_message" msgid="1277346543068257549">"Algumas funcionalidades são limitadas enquanto o telemóvel arrefece.\nToque para obter mais informações."</string>
@@ -778,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"gravação de ecrã"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Modo de espera"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamanho do tipo de letra"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Diminuir"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controlos da janela de ampliação"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumentar zoom"</string>
@@ -810,7 +807,8 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controlo adicionado.}many{# controlos adicionados.}other{# controlos adicionados.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Adicionar <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Quando adicionar a app <xliff:g id="APPNAME">%s</xliff:g>, esta pode adicionar controlos e conteúdos a este painel. Em algumas apps, pode escolher que controlos são apresentados aqui."</string>
+ <string name="controls_panel_authorization" msgid="4665218066461350247">"A app <xliff:g id="APPNAME">%s</xliff:g> pode escolher que controlos e conteúdos são apresentados aqui."</string>
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remover controlos para a app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado aos favoritos"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionados aos favoritos, posição <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
@@ -828,12 +826,13 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outro"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Adicione aos controlos de dispositivos"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Remover"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloq."</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Mostrar e controlar dispositivos a partir do ecrã de bloqueio?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Pode adicionar controlos para os seus dispositivos externos ao ecrã de bloqueio.\n\nA app do dispositivo pode permitir controlar alguns dispositivos sem desbloquear o seu telemóvel ou tablet.\n\nPode fazer alterações em qualquer altura nas Definições."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Controlar dispositivos a partir do ecrã de bloqueio?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Pode controlar alguns dispositivos sem desbloquear o seu telemóvel ou tablet.\n\nA app do dispositivo determina que dispositivos podem ser controlados desta forma."</string>
+ <string name="controls_settings_trivial_controls_dialog_message" msgid="397178734990952575">"Pode controlar alguns dispositivos sem desbloquear o seu telemóvel ou tablet. A app do dispositivo determina que dispositivos podem ser controlados desta forma."</string>
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Não"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sim"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contém letras ou símbolos."</string>
@@ -881,6 +880,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controlos"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controlos"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adicionar app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Remover app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicione saídas"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
@@ -1045,4 +1045,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Mudar para perfil de trabalho"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Definições do ecrã de bloqueio"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Câmara bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Câmara e microfone bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfone bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo Prioridade ativado"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 1b9e0150ce26..c778371a8177 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Se você informar um PIN incorreto na próxima tentativa, seu perfil de trabalho e os dados dele serão excluídos."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Se você informar uma senha incorreta na próxima tentativa, seu perfil de trabalho e os dados dele serão excluídos."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toque no sensor de impressão digital"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ícone de impressão digital"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Não foi possível reconhecer o rosto Use a impressão digital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Aba de notificações."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configurações rápidas."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configurações rápidas e aba de notificações."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Tela de bloqueio."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Tela de bloqueio de trabalho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brilho"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversão de cores"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correção de cor"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamanho da fonte"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gerenciar usuários"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Concluído"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Fechar"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie para conferir as notificações antigas"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie p/ acessar notificações antigas"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Sua organização é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"A organização <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"gravação de tela"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Em espera"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamanho da fonte"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Diminuir"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controles da janela de ampliação"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumentar zoom"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}many{# de controles adicionados.}other{# controles adicionados.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Adicionar o app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Quando você adiciona o app <xliff:g id="APPNAME">%s</xliff:g>, ele pode incluir controles e conteúdo neste painel. Em alguns casos, é possível escolher quais controles aparecem aqui."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remover controles do app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outro"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Adicionar aos controles do dispositivo"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Remover"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloq."</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Mostrar e controlar dispositivos na tela de bloqueio?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Você pode adicionar à tela de bloqueio controles para dispositivos externos.\n\nO app do dispositivo pode permitir que você controle alguns dispositivos sem desbloquear o smartphone ou tablet.\n\nÉ possível fazer mudanças a qualquer momento nas Configurações."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Controlar dispositivos na tela de bloqueio?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"É possível controle alguns dispositivos sem desbloquear o smartphone ou tablet.\n\nO app do dispositivo determina quais dispositivos podem ser controlados dessa maneira."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Agora não"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sim"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contém letras ou símbolos"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controles"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adicionar app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Remover o app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicionar saídas"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Não foi possível fazer a transmissão"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use pelo menos 4 caracteres"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use menos de 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Pelo menos um dispositivo está disponível"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Trocar de tela agora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Abra o smartphone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Trocar de tela?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para uma resolução maior, use a câmera traseira"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para uma resolução maior, vire o smartphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável sendo aberto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável sendo virado"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateria restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Alternar para o perfil de trabalho"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Configurações de tela de bloqueio"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Câmara bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Câmera e microfone bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfone bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo de prioridade ativado"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/tiles_states_strings.xml b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
index cea45323069f..28c07f40b6b9 100644
--- a/packages/SystemUI/res/values-pt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Desativado"</item>
<item msgid="5966994759929723339">"Ativado"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Indisponível"</item>
+ <item msgid="2478289035899842865">"Desativado"</item>
+ <item msgid="5137565285664080143">"Ativado"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 907b9c185c3c..62eb9f003e12 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Dacă la următoarea încercare introduci un cod PIN incorect, profilul de serviciu și datele sale vor fi șterse."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Dacă la următoarea încercare introduci o parolă incorectă, profilul de serviciu și datele sale vor fi șterse."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Atinge senzorul de amprente"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Pictograma amprentă"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Chipul nu a fost recunoscut. Folosește amprenta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Fereastră pentru notificări."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Setări rapide."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Fereastră de Setări rapide și notificări."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ecranul de blocare."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ecran de blocare pentru serviciu"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Închide"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminozitate"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversarea culorilor"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corecția culorii"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Dimensiunea fontului"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gestionează utilizatorii"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Terminat"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Închide"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"înregistrare de ecran"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Fără titlu"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Dimensiunea fontului"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Micșorează"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Mărește"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fereastra de mărire"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Comenzi pentru fereastra de mărire"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Mărește"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{S-a adăugat # comandă.}few{S-au adăugat # comenzi.}other{S-au adăugat # de comenzi.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Eliminată"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Adaugi <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Când adaugi <xliff:g id="APPNAME">%s</xliff:g>, aplicația poate să adauge comenzi și conținut pe acest panou. În anumite aplicații, poți să alegi comenzile care se afișează aici."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Elimini comenzile pentru <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Marcată ca preferată"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Marcată ca preferată, poziția <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"S-a anulat marcarea ca preferată"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Altul"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Adaugă la comenzile dispozitivelor"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Adaugă"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Exclude"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Sugerat de <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Dispozitiv blocat"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Afișezi și controlezi dispozitivele de pe ecranul de blocare?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Poți adăuga comenzi pentru dispozitivele externe pe ecranul de blocare.\n\nAplicația de pe dispozitiv îți poate permite să controlezi unele dispozitive fără să deblochezi telefonul.\n\nPoți face modificări oricând în setări."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Controlezi dispozitivele de pe ecranul de blocare?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Poți controla unele dispozitive fără să deblochezi telefonul sau tableta.\n\nAplicația de pe dispozitiv stabilește dispozitivele care pot fi controlate astfel."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nu, mulțumesc"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Da"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Codul PIN conține litere sau simboluri"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Adaugă comenzi"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editează comenzile"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adaugă o aplicație"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Elimină aplicația"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adaugă ieșiri"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"S-a selectat un dispozitiv"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Este disponibil cel puțin un dispozitiv"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Schimbă ecranul acum"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Deschide telefonul"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Schimbi ecranul?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Pentru o rezoluție mai mare, folosește camera foto posterioară"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Pentru o rezoluție mai mare, deschide telefonul"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispozitiv pliabil care este desfăcut"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispozitiv pliabil care este întors"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> baterie rămasă"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Comută la profilul de serviciu"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Închide"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Setările ecranului de blocare"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Conexiune Wi-Fi indisponibilă"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera foto a fost blocată"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera foto și microfonul sunt blocate"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfonul a fost blocat"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modul Cu prioritate este activat"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
index 782afc5d7299..5a5eb9f6788c 100644
--- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Dezactivat"</item>
<item msgid="5966994759929723339">"Activat"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Indisponibil"</item>
+ <item msgid="2478289035899842865">"Dezactivat"</item>
+ <item msgid="5137565285664080143">"Activat"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 2b8c776915bd..9a8973513dd8 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Если вы неправильно введете PIN-код ещё раз, ваш рабочий профиль и его данные будут удалены."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Если вы неправильно введете пароль ещё раз, ваш рабочий профиль и его данные будут удалены."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Прикоснитесь к сканеру отпечатков пальцев."</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Значок отпечатка пальца"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не удалось распознать лицо. Используйте отпечаток."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Заблокировано"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыть"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яркость"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Инверсия цветов"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Коррекция цвета"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Размер шрифта"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Управление пользователями"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Готово"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Закрыть"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"запись экрана"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без названия"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Переход в режим ожидания"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Размер шрифта"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Уменьшить"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Увеличить"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Окно увеличения"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Настройки окна увеличения"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Увеличить"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Добавлен # элемент управления.}one{Добавлен # элемент управления.}few{Добавлено # элемента управления.}many{Добавлено # элементов управления.}other{Добавлено # элемента управления.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Удалено"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Добавить приложение \"<xliff:g id="APPNAME">%s</xliff:g>\"?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Приложение \"<xliff:g id="APPNAME">%s</xliff:g>\" может добавить на эту панель элементы управления и контент. Некоторые приложения позволяют выбирать, какие элементы будут здесь показаны."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Удалить приложение \"<xliff:g id="APPNAME">%s</xliff:g>\" с панели управления устройствами?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Добавлено в избранное"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Добавлено в избранное на позицию <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Не добавлено в избранное"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Другое"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Добавьте виджеты управления устройствами"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Добавить"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Удалить"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Предложено приложением \"<xliff:g id="APP">%s</xliff:g>\""</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Устройство заблокировано"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Разрешить показывать устройства и управлять ими на заблокированном экране?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Вы можете добавить элементы управления внешними устройствами на заблокированный экран.\n\nПриложение на вашем устройстве может разрешать управление некоторыми устройствами с заблокированного экрана.\n\nИзменить параметры можно в любое время в настройках."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Управлять устройствами на заблокированном экране?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Вы можете управлять некоторыми устройствами с заблокированного телефона или планшета.\n\nКакими именно устройствами можно управлять, зависит от приложения на вашем устройстве."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Не сейчас"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Да"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-код содержит буквы или символы"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Добавить виджеты"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Изменить виджеты"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Добавить приложение"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Удалить приложение"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Добавление устройств вывода"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Группа"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Выбрано 1 устройство"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Не удалось запустить трансляцию"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не удалось сохранить. Повторите попытку."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не удалось сохранить."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Минимальное количество символов – 4"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Максимальное количество символов – 16"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Доступно хотя бы одно устройство."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Нажмите и удерживайте ярлык"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Отмена"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Переключиться на другой экран"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Разложите телефон"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Переключиться на другой экран?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Используйте основную камеру, чтобы делать снимки с более высоким разрешением."</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Переверните телефон и используйте основную камеру, чтобы делать снимки с более высоким разрешением."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Складное устройство в разложенном виде"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Перевернутое складное устройство"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Уровень заряда батареи: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Перейти в рабочий профиль"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрыть"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Настройки блокировки экрана"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Функция Wi-Fi недоступна"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера заблокирована"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера и микрофон заблокированы"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон заблокирован"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Режим \"Только важные\" включен"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/tiles_states_strings.xml b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
index 9a4960b1ada9..cd140791bbd5 100644
--- a/packages/SystemUI/res/values-ru/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Отключено"</item>
<item msgid="5966994759929723339">"Включено"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Недоступно"</item>
+ <item msgid="2478289035899842865">"Выключено"</item>
+ <item msgid="5137565285664080143">"Включено"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 8c8511989e2e..c98a9df69256 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ඔබ ඊළඟ උත්සාහයේදී වැරදි PIN එකක් ඇතුළු කළහොත්, ඔබේ කාර්යාල පැතිකඩ සහ එහි දත්ත මකනු ඇත."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ඔබ ඊළඟ උත්සාහයේදී වැරදි මුරපදයක් ඇතුළු කළහොත්, ඔබේ කාර්යාල පැතිකඩ සහ එහි දත්ත මකනු ඇත."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ඇඟිලි සලකුණු නිරූපකය"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"මුහුණ හැඳිනිය නොහැක. ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත ක."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"කාර්යාල අගුලු තිරය"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"වසන්න"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"දීප්තිමත් බව"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"වර්ණ අපවර්තනය"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"වර්ණ නිවැරදි කිරීම"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"අකුරු විශාලත්වය"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"පරිශීලකයන් කළමනාකරණය කරන්න"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"නිමයි"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"වසන්න"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"තිර පටිගත කිරීම"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"මාතෘකාවක් නැත"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"පොරොත්තු"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"අකුරු විශාලත්වය"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"වඩා කුඩා කරන්න"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"වඩා විශාල කරන්න"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"විශාලන කවුළුව"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"විශාලනය කිරීමේ කවුළු පාලන"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"විශාලනය වැඩි කරන්න"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# පාලනයක් එක් කර ඇත.}one{පාලන #ක් එක් කර ඇත.}other{පාලන #ක් එක් කර ඇත.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"ඉවත් කළා"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> එක් කරන්න ද?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"ඔබ <xliff:g id="APPNAME">%s</xliff:g> එක් කළ විට, එයට මෙම පැනලයට පාලන සහ අන්තර්ගතය එක් කළ හැක. සමහර යෙදුම්වල, ඔබට මෙහි පෙන්වන්නේ කුමන පාලන ද යන්න තෝරා ගැනීමට හැක."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> සඳහා පාලන ඉවත් කරන්න ද?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"ප්‍රියතම කළා"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"ප්‍රියතම කළා, තත්ත්ව <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ප්‍රියතම වෙතින් ඉවත් කළා"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"වෙනත්"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"උපාංග පාලන වෙත එක් කරන්න"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"එක් කරන්න"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"ඉවත් කරන්න"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"යෝජනා කළේ <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"උපාංගය අගුලු දමා ඇත"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"අගුලු තිරයෙන් උපාංග පෙන්වීම සහ පාලනය සිදු කරන්නද?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ඔබට ඔබගේ බාහිර උපාංග සඳහා පාලන අගුලු තිරයට එක් කළ හැකිය.\n\nඔබගේ උපාංග යෙදුම ඔබගේ දුරකථනය හෝ ටැබ්ලටය අගුලු හැරීමෙන් තොරව සමහර උපාංග පාලනය කිරීමට ඉඩ ලබා දේ.\n\nඔබට සැකසීම් තුළ ඕනෑම වේලාවක වෙනස් කිරීම් සිදු කළ හැකිය."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"අගුලු තිරයෙන් උපාංග පාලනය කරන්නද?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"ඔබගේ දුරකථනය හෝ ටැබ්ලටය අගුලු හැරීමෙන් තොරව ඔබට සමහර උපාංග පාලනය කළ හැකිය.\n\nඔබගේ උපාංග යෙදුම මේ ආකාරයෙන් පාලනය කළ හැකි උපාංග තීරණය කරයි."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"එපා ස්තුතියි"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ඔව්"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN හි අකුරු හෝ සංකේත අඩංගු වේ"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"පාලන එක් කරන්න"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"පාලන සංස්කරණය කරන්න"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"යෙදුම එක් කරන්න"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"යෙදුම ඉවත් කරන්න"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"ප්‍රතිදාන එක් කරන්න"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"සමූහය"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"උපාංග 1ක් තෝරන ලදී"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"විකාශනය කළ නොහැකිය"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"සුරැකිය නොහැකිය. නැවත උත්සාහ කරන්න."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"සුරැකිය නොහැකිය."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"අවම වශයෙන් අනුලකුණු 4ක් භාවිතා කරන්න"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"අනුලකුණු 16කට වඩා අඩුවෙන් භාවිතා කරන්න"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• අවම වශයෙන් එක උපාංගයක් ලැබේ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ස්පර්ශ කර අල්ලා සිටීමේ කෙටිමඟ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"අවලංගු කරන්න"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"දැන් තිර මාරු කරන්න"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"දුරකථනය දිගහරින්න"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"තිර මාරු කරන්න ද?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ඉහළ විභේදනය සඳහා, පසුපස කැමරාව භාවිතා කරන්න"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ඉහළ විභේදනය සඳහා, දුරකථනය හරවන්න"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"දිග හැරෙමින් පවතින නැමිය හැකි උපාංගය"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"වටා පෙරළෙමින් තිබෙන නැමිය හැකි උපාංගය"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> බැටරිය ඉතිරිව ඇත"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"කාර්යාල පැතිකඩ වෙත මාරු වන්න"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"වසන්න"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"අගුළු තිර සැකසීම්"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ලද නොහැක"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"කැමරාව අවහිරයි"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"කැමරාව සහ මයික්‍රොෆෝනය අවහිරයි"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"මයික්‍රොෆෝනය අවහිරයි"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ප්‍රමුඛතා මාදිලිය සක්‍රීයයි"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/tiles_states_strings.xml b/packages/SystemUI/res/values-si/tiles_states_strings.xml
index c9312ff08040..fcd768bfc4e3 100644
--- a/packages/SystemUI/res/values-si/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-si/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"ක්‍රියාවිරහිතයි"</item>
<item msgid="5966994759929723339">"ක්‍රියාත්මකයි"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"නොමැත"</item>
+ <item msgid="2478289035899842865">"ක්‍රියාවිරහිතයි"</item>
+ <item msgid="5137565285664080143">"ක්‍රියාත්මකයි"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 262e269dd790..c732593d484f 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ak pri ďalšom pokuse zadáte nesprávny PIN, váš pracovný profil a jeho dáta budú odstránené."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ak pri ďalšom pokuse zadáte nesprávne heslo, váš pracovný profil a jeho dáta budú odstránené."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotknite sa senzora odtlačkov prstov"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona odtlačku prsta"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tvár sa nedá rozpoznať. Použite odtlačok prsta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel upozornení."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rýchle nastavenia."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Rýchle nastavenia a panel upozornení"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Uzamknutá obrazovka"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Uzamknutá obrazovka pracovného profilu"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zavrieť"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Jas"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzia farieb"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Úprava farieb"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Veľkosť písma"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Spravovať používateľov"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Hotovo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zavrieť"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Spustiť"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Žiadne upozornenia"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Žiadne nové upozornenia"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odomknutím si zobrazte staršie upozor."</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odomknutím zobrazíte staršie upozornenia"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Toto zariadenie spravuje tvoj rodič"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša organizácia spravuje toto zariadenie a môže sledovať sieťovú premávku"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> vlastní toto zariadenie a môže sledovať sieťovú premávku"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"nahrávanie obrazovky"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Pohotovostný režim"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Veľkosť písma"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Zmenšiť"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Zväčšiť"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Okno priblíženia"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ovládacie prvky okna priblíženia"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Priblížiť"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Bol pridaný # ovládací prvok.}few{Boli pridané # ovládacie prvky.}many{# controls added.}other{Bolo pridaných # ovládacích prvkov.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Odstránené"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Chcete pridať aplikáciu <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Keď pridáte aplikáciu <xliff:g id="APPNAME">%s</xliff:g>, bude môcť pridať ovládanie a obsah na tento panel. V prípade niektorých aplikácií môžete vybrať, ktoré ovládacie prvky sa tu majú zobraziť."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Chcete odstrániť ovládanie aplikácie <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Pridané medzi obľúbené"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Pridané medzi obľúbené, pozícia <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odstránené z obľúbených"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Iné"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Pridanie do ovládania zariadení"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Pridať"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Odstrániť"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Navrhuje <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Uzamknuté zariadenie"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Chcete zobrazovať a ovládať zariadenia na uzamknutej obrazovke?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Na uzamknutú obrazovku si môžete pridať ovládanie externých zariadení.\n\nAplikácia zariadenia vám môže umožniť ovládať niektoré zariadenia bez odomknutia telefónu či tabletu.\n\nZmeny môžete vykonať kedykoľvek v Nastaveniach."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Chcete ovládať zariadenia na uzamknutej obrazovke?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Niektoré zariadenia môžete ovládať bez odomknutia telefónu či tabletu.\n\nAplikácia zariadenia určuje, ktoré zariadenia sa dajú týmto spôsobom ovládať."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nie, vďaka"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Áno"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN obsahuje písmená či symboly"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Pridať ovládače"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Upraviť ovládače"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Pridať aplikáciu"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Odstrániť aplikáciu"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Pridanie výstupov"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 vybrané zariadenie"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• K dispozícii je minimálne jedno zariadenie"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Prepnite obrazovky"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Rozloženie telefónu"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Chcete prepnúť obrazovky?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Ak chcete vyššie rozlíšenie, použite zadnú kameru"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Ak chcete vyššie rozlíšenie, prevráťte telefón"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rozloženie skladacieho zariadenia"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Prevrátenie skladacieho zariadenia"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g> batérie"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Prepnúť na pracovný profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zavrieť"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Nastavenia uzamknutej obrazovky"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi‑Fi nie je k dispozícii"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokovaná"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera a mikrofón sú blokované"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofón je blokovaný"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Režim priority je zapnutý"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/tiles_states_strings.xml b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
index 3540eabb8205..660f85d365e2 100644
--- a/packages/SystemUI/res/values-sk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Vypnuté"</item>
<item msgid="5966994759929723339">"Zapnuté"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nedostupné"</item>
+ <item msgid="2478289035899842865">"Vypnuté"</item>
+ <item msgid="5137565285664080143">"Zapnuté"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 012b14f959e2..79e7b5ab0762 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Če pri naslednjem poskusu vnesete napačno kodo PIN, bodo delovni profil in podatki v njem izbrisani."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Če pri naslednjem poskusu vnesete napačno geslo, bodo delovni profil in podatki v njem izbrisani."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotaknite se tipala prstnih odtisov"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona prstnih odtisov"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Obraza ni mogoče prepoznati. Uporabite prstni odtis."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -187,8 +186,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija <xliff:g id="NUMBER">%d</xliff:g> odstotkov."</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Baterija je napolnjena na <xliff:g id="PERCENTAGE">%1$d</xliff:g> %% – <xliff:g id="TIME">%2$s</xliff:g>."</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Baterija se polni, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> odstotkov."</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Baterija je napolnjena na <xliff:g id="PERCENTAGE">%d</xliff:g> %% – zaradi zaščite baterije je polnjenje začasno zaustavljeno."</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Baterija je napolnjena na <xliff:g id="PERCENTAGE">%1$d</xliff:g> %% – <xliff:g id="TIME">%2$s</xliff:g> je zaradi zaščite baterije polnjenje začasno zaustavljeno."</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Baterija je napolnjena na <xliff:g id="PERCENTAGE">%d</xliff:g> odstotkov. Zaradi zaščite baterije je polnjenje začasno zaustavljeno."</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Baterija je napolnjena na <xliff:g id="PERCENTAGE">%1$d</xliff:g> odstotkov – <xliff:g id="TIME">%2$s</xliff:g>. Zaradi zaščite baterije je polnjenje začasno zaustavljeno."</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"Prikaži vsa obvestila"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter omogočen."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Zvonjenje z vibriranjem."</string>
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Zaslon z obvestili."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hitre nastavitve."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hitre nastavitve in zaslon z obvestili"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaklenjen zaslon"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaklenjen zaslon delovnega profila"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zapri"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Svetlost"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzija barv"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Popravljanje barv"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Velikost pisave"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Upravljanje uporabnikov"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Končano"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zapri"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"snemanje zaslona"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Brez naslova"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje pripravljenosti"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Velikost pisave"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Pomanjšanje"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Povečanje"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Povečevalno okno"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrolniki povečevalnega okna"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Povečaj"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrolnik je dodan.}one{# kontrolnik je dodan.}two{# kontrolnika sta dodana.}few{# kontrolniki so dodani.}other{# kontrolnikov je dodanih.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Odstranjeno"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Želite dodati aplikacijo <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Ko dodate aplikacijo <xliff:g id="APPNAME">%s</xliff:g>, lahko ta doda kontrolnike in vsebino v to podokno. V nekaterih aplikacijah lahko izberete, kateri kontrolniki so prikazani tukaj."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Želite odstraniti kontrolnike za aplikacijo <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano med priljubljene"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano med priljubljene, položaj <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odstranjeno iz priljubljenih"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Dodajanje med kontrolnike naprave"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Odstrani"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Predlagala aplikacija <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Naprava je zaklenjena"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Želite prikazati in upravljati naprave na zaklenjenem zaslonu?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Kontrolnike za zunanje naprave lahko dodate na zaklenjen zaslon.\n\nAplikacija v napravi vam bo morda omogočala upravljanje nekaterih naprav brez odklepanja telefona ali tabličnega računalnika.\n\nTe spremembe lahko kadar koli izvedete v nastavitvah."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Želite upravljati naprave na zaklenjenem zaslonu?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Nekatere naprave lahko upravljate brez odklepanja telefona ali tabličnega računalnika.\n\nAplikacija v napravi določa, katere naprave je mogoče upravljati na ta način."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, hvala"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Da"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Koda PIN vsebuje črke ali simbole"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Dodajte kontrolnike"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Uredite kontrolnike"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikacijo"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Odstrani aplikacijo"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajanje izhodov"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Izbrana je ena naprava"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Na voljo mora biti vsaj ena naprava."</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Preklopi zaslona zdaj"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Razprite telefon."</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Želite preklopiti zaslona?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Za višjo ločljivost uporabite hrbtni fotoaparat"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za višjo ločljivost obrnite telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Razpiranje zložljive naprave"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Obračanje zložljive naprave"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Preostanek energije baterije: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Preklopi na delovni profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zapri"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Nastavitve zaklepanja zaslona"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ni na voljo."</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Fotoaparat je blokiran."</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Fotoaparat in mikrofon sta blokirana."</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran."</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prednostni način je vklopljen."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/tiles_states_strings.xml b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
index 985b7796c567..d7e62caac28d 100644
--- a/packages/SystemUI/res/values-sl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Izklopljeno"</item>
<item msgid="5966994759929723339">"Vklopljeno"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ni na voljo"</item>
+ <item msgid="2478289035899842865">"Izklopljeno"</item>
+ <item msgid="5137565285664080143">"Vklopljeno"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index a9c8784a0251..e90f1c038a7e 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Nëse fut një kod PIN të pasaktë në tentativën tjetër, profili yt i punës dhe të dhënat e tij do të fshihen."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Nëse fut një fjalëkalim të pasaktë në tentativën tjetër, profili yt i punës dhe të dhënat e tij do të fshihen."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Prek sensorin e gjurmës së gishtit"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona e gjurmës së gishtit"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nuk mund ta dallojë fytyrën. Përdor më mirë gjurmën e gishtit."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Streha e njoftimeve."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Cilësimet e shpejta."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"\"Cilësimet e shpejta\" dhe \"Streha e njoftimeve\"."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ekrani i kyçjes."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekrani i kyçjes së punës"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Mbylle"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ndriçimi"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Anasjellja e ngjyrës"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korrigjimi i ngjyrës"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Madhësia e fontit"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Menaxho përdoruesit"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"U krye"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Mbyll"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"regjistrim i ekranit"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Pa titull"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Në gatishmëri"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Madhësia e fontit"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Zvogëlo"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Zmadho"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Dritarja e zmadhimit"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrollet e dritares së zmadhimit"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zmadho"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{U shtua # kontroll.}other{U shtuan # kontrolle.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"E hequr"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Të shtohet <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Kur shton <xliff:g id="APPNAME">%s</xliff:g>, ai mund t\'i shtojë kontrolle dhe përmbajtje këtij paneli. Në disa aplikacione, mund të zgjedhësh se cilat kontrolle shfaqen këtu."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Të hiqen kontrollet për <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"E shtuar te të preferuarat"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"E shtuar te të preferuarat, pozicioni <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"E hequr nga të preferuarat"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Tjetër"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Shto te kontrollet e pajisjes"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Shto"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Hiq"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Sugjeruar nga <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Pajisja është e kyçur"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Të shfaqen dhe të kontrollohen pajisjet nga ekrani i kyçjes?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Mund të shtosh kontrolle për pajisjet e tua të jashtme në ekranin e kyçjes.\n\nAplikacioni në pajisjen tënde mund të të lejojë të kontrollosh disa pajisje pa shkyçur telefonin apo tabletin.\n\nMund të bësh ndryshime në çdo kohë te \"Cilësimet\"."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Të kontrollohen pajisjet nga ekrani i kyçjes?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Mund të kontrollosh disa pajisje pa shkyçur telefonin apo tabletin.\n\nAplikacioni në pajisjen tënde përcakton se cilat pajisje mund të kontrollohen në këtë mënyrë."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Jo, faleminderit"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Po"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Kodi PIN përmban shkronja ose simbole"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Shto kontrollet"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Modifiko kontrollet"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Shto një aplikacion"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Hiqe aplikacionin"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Shto daljet"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupi"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 pajisje e zgjedhur"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ofrohet të paktën një pajisje"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Ndërro ekranet tani"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Shpalos telefonin"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Të ndërrohen ekranet?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Për rezolucion më të lartë, përdor kamerën e pasme"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Për rezolucion më të lartë, përmbys telefonin"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Pajisja e palosshme duke u hapur"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Pajisja e palosshme duke u rrotulluar"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Përqindja e mbetur e baterisë: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Kalo te profili i punës"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Mbyll"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Cilësimet e ekranit të kyçjes"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nuk ofrohet"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera u bllokua"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dhe mikrofoni u bllokuan"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofoni u bllokua"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modaliteti i përparësisë aktiv"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
index 5862e2ef2b1c..45f63bf8e2e8 100644
--- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Joaktiv"</item>
<item msgid="5966994759929723339">"Aktiv"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nuk ofrohet"</item>
+ <item msgid="2478289035899842865">"Joaktiv"</item>
+ <item msgid="5137565285664080143">"Aktiv"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index a9df97a4007d..674985cecbb2 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ако унесете нетачан PIN при следећем покушају, избрисаћемо пословни профил и његове податке."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ако унесете нетачну лозинку при следећем покушају, избрисаћемо пословни профил и његове податке."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Додирните сензор за отисак прста"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Икона отиска прста"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Лице није препознато. Користите отисак прста."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Закључан екран за посао"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Затвори"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Осветљеност"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Инверзија боја"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекција боја"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Величина фонта"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Управљаjте корисницима"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Готово"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Затвори"</string>
@@ -401,7 +400,7 @@
<string name="media_projection_action_text" msgid="3634906766918186440">"Започни"</string>
<string name="empty_shade_text" msgid="8935967157319717412">"Нема обавештења"</string>
<string name="no_unseen_notif_text" msgid="395512586119868682">"Нема нових обавештења"</string>
- <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Откључајте да видите старија обавештења"</string>
+ <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Откључајте за старија обавештења"</string>
<string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Овим уређајем управља родитељ"</string>
<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>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"снимање екрана"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без наслова"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Стање приправности"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Величина фонта"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Умањите"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Увећајте"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозор за увећање"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроле прозора за увећање"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Увећајте"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# контрола је додата.}one{# контрола је додата.}few{# контроле су додате.}other{# контрола је додато.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Уклоњено"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Желите ли да додате <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Када додате апликацију <xliff:g id="APPNAME">%s</xliff:g>, она може да додаје контроле и садржај у ово окно. У неким апликацијама можете да изаберете које ће се контроле овде приказивати."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Желите да уклоните контроле за <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Означено је као омиљено"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Означено је као омиљено, <xliff:g id="NUMBER">%d</xliff:g>. позиција"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Уклоњено је из омиљених"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Друго"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Додајте у контроле уређаја"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Додај"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Уклони"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Предлаже <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Уређај је закључан"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Желите ли да приказујете и контролишете уређаје са закључаног екрана?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Можете да додате контроле за спољне уређаје на закључани екран.\n\nАпликација на уређају може да вам омогући да контролишете неке уређаје без откључавања телефона или таблета.\n\nТо можете да промените кад год желите у Подешавањима."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Желите ли да контролишете уређаје са закључаног екрана?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Неке уређаје можете да контролишете без откључавања телефона или таблета.\n\nАпликација на уређају одређује који уређаји могу да се контролишу на овај начин."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Не, хвала"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Да"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN садржи слова или симболе"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Додај контроле"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Измени контроле"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Додај апликацију"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Уклони апликацију"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Додајте излазе"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Изабран је 1 уређај"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• да је доступан барем један уређај"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Додирните и задржите пречицу"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Откажи"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Замени екране"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Отворите телефон"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Желите да замените екране?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"За већу резолуцију користите задњу камеру"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"За већу резолуцију обрните телефон"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Уређај на преклоп се отвара"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Уређај на преклоп се обрће"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Преостало је још<xliff:g id="PERCENTAGE">%s</xliff:g> батерије"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Пређи на пословни профил"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Затвори"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Подешавања закључаног екрана"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi није доступан"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера је блокирана"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера и микрофон су блокирани"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон је блокиран"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетни режим је укључен"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/tiles_states_strings.xml b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
index e817eea952ec..c959bfb0eb73 100644
--- a/packages/SystemUI/res/values-sr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Искључено"</item>
<item msgid="5966994759929723339">"Укључено"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Недоступно"</item>
+ <item msgid="2478289035899842865">"Искључено"</item>
+ <item msgid="5137565285664080143">"Укључено"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index d839a1117401..5388b00b6746 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jobbprofilen och dess data raderas om du anger fel pinkod vid nästa försök."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Din jobbprofil och dess data raderas om du anger fel lösenord vid nästa försök."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Tryck på fingeravtryckssensorn"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikon för fingeravtryck"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansiktet kändes inte igen. Använd fingeravtryck."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meddelandepanel."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snabbinställningar."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Snabbinställningar och meddelandepanel."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låsskärm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låsskärm för arbete"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Stäng"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ljusstyrka"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Färginvertering"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Färgkorrigering"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Teckenstorlek"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Hantera användare"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Klart"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Stäng"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"skärminspelning"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Viloläge"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Teckenstorlek"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Förminska"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Förstora"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Förstoringsfönster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Inställningar för förstoringsfönster"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zooma in"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontroll har lagts till.}other{# kontroller har lagts till.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Har tagits bort"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Vill du lägga till <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"När du lägger till <xliff:g id="APPNAME">%s</xliff:g> kan den lägga till kontroller och innehåll i den här panelen. I vissa appar kan du styra vilka kontroller som visas här."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vill du ta bort inställningarna för <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Har lagts till som favorit"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Har lagts till som favorit, plats <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Har tagits bort från favoriter"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Övrigt"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Lägg till i enhetsstyrning"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Lägg till"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Ta bort"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Förslag från <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Enheten är låst"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vill du se och styra enheter på låsskärmen?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Du kan lägga till reglage att styra externa enheter med på låsskärmen.\n\nVissa enheter kan gå att styra med appen på enheten utan att du behöver låsa upp telefonen eller surfplattan.\n\nDu kan när som helst ändra detta i inställningarna."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vill du styra enheter på låsskärmen?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Du kan styra vissa enheter utan att låsa upp telefonen eller surfplattan.\n\nVilka enheter som går att styra på det här sättet beror på appen på enheten."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nej tack"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Pinkoden innehåller bokstäver eller symboler"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Lägg till snabbkontroller"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Redigera snabbkontroller"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Lägg till app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Ta bort app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Lägg till utgångar"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupp"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 enhet har valts"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Det gick inte att sända ut"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Använd minst 4 tecken"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Använd färre än 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• minst en enhet är tillgänglig"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Byt skärm nu"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Vik ut telefonen"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vill du byta skärm?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Använd den bakre kameran för högre upplösning"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Vänd telefonen för högre upplösning"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En vikbar enhet viks upp"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"En vikbar enhet vänds"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> av batteriet återstår"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Byt till jobbprofilen"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Stäng"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Inställningar för låsskärm"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi är inte tillgängligt"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameran är blockerad"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameran och mikrofonen är blockerade"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen är blockerad"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetsläge är aktiverat"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/tiles_states_strings.xml b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
index 45169aa8b1f4..28717dfa5229 100644
--- a/packages/SystemUI/res/values-sv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Av"</item>
<item msgid="5966994759929723339">"På"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Inte tillgängligt"</item>
+ <item msgid="2478289035899842865">"Av"</item>
+ <item msgid="5137565285664080143">"På"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index c303c09375aa..118e24a7864e 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ukiweka PIN isiyo sahihi utakapojaribu tena, wasifu wako wa kazini utafutwa pamoja na data yake."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ukiweka nenosiri lisilo sahihi utakapojaribu tena, wasifu wako wa kazini utafutwa pamoja na data yake."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Gusa kitambua alama ya kidole"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Aikoni ya alama ya kidole"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Imeshindwa kutambua uso. Tumia alama ya kidole."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kivuli cha arifa."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mipangilio ya haraka."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Mipangilio ya haraka na Sehemu ya arifa."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Skrini iliyofungwa."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrini iliyofungwa ya kazini"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Funga"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ung\'avu"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ugeuzaji rangi"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Usahihishaji wa rangirangi"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Ukubwa wa fonti"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Dhibiti watumiaji"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Nimemaliza"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Funga"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"kurekodi skrini"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Wimbo hauna jina"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Hali tuli"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Ukubwa wa Fonti"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Punguza"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Kuza"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Dirisha la Ukuzaji"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vidhibiti vya Dirisha la Ukuzaji"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Vuta karibu"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Umeweka kidhibiti #.}other{Umeweka vidhibiti #.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Kimeondolewa"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Ungependa kuweka <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Unapoweka <xliff:g id="APPNAME">%s</xliff:g>, inaweza kuweka vidhibiti na maudhui kwenye kidirisha hiki. Katika baadhi ya programu, unaweza kuchagua ni vidhibiti vipi vionekane hapa."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Ungependa kuondoa vidhibiti vya <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Kimewekwa kwenye vipendwa"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Kimewekwa kwenye vipendwa, nafasi ya <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Kimeondolewa kwenye vipendwa"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Nyingine"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Weka kwenye vidhibiti vya vifaa"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Weka"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Ondoa"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Kimependekezwa na <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Kifaa kimefungwa"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Ungependa kuonyesha na udhibiti vifaa kwenye skrini iliyofungwa?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Unaweza kuweka vidhibiti kwa ajili ya vifaa vyako vya nje kwenye skrini iliyofungwa.\n\nProgramu ya kifaa chako huenda ikakuruhusu udhibiti baadhi ya vifaa bila kufungua simu au kompyuta kibao yako.\n\nUnaweza kufanya mabadiliko muda wowote kwenye Mipangilio."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Ungependa kudhibiti vifaa kwenye skrini iliyofungwa?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Unaweza kudhibiti baadhi ya vifaa bila kufungua simu au kompyuta kibao yako.\n\nProgramu ya kifaa chako hubainisha ni vifaa vipi vinaweza kudhibitiwa kwa njia hii."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Hapana"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ndiyo"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ina herufi au alama"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Weka vidhibiti"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Badilisha vidhibiti"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Weka programu"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Ondoa programu"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Weka vifaa vya kutoa sauti"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Kikundi"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Umechagua kifaa 1"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Imeshindwa kutuma arifa"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Tumia angalau herufi 4"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Tumia herufi chini ya 16"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Angalau kifaa kimoja kinapatikana"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Badilisha skrini sasa"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Kunjua simu"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Ungependa kubadilisha skrini?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Kwa ubora wa juu, tumia kamera ya nyuma"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Kwa ubora wa juu, geuza simu"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Kifaa kinachokunjwa kikikunjuliwa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Kifaa kinachokunjwa kikigeuzwa"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Chaji ya betri imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Tumia wasifu wa kazini"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Funga"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Mipangilio ya skrini iliyofungwa"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi haipatikani"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera imezuiwa"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera na maikrofoni zimezuiwa"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Maikrofoni imezuiwa"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Hali ya kipaumbele imewashwa"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/tiles_states_strings.xml b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
index aad00999f0f6..2fe40603bc7d 100644
--- a/packages/SystemUI/res/values-sw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Imezimwa"</item>
<item msgid="5966994759929723339">"Imewashwa"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Haipatikani"</item>
+ <item msgid="2478289035899842865">"Umezima"</item>
+ <item msgid="5137565285664080143">"Umewasha"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 45b137a9acec..59becc69506c 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -62,7 +62,6 @@
<dimen name="qs_security_footer_background_inset">0dp</dimen>
<dimen name="qs_panel_padding_top">8dp</dimen>
- <dimen name="qs_panel_padding_top_combined_headers">@dimen/qs_panel_padding_top</dimen>
<!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
<dimen name="large_dialog_width">472dp</dimen>
@@ -88,4 +87,7 @@
<!-- Biometric Auth pattern view size, better to align keyguard_security_width -->
<dimen name="biometric_auth_pattern_view_size">348dp</dimen>
+
+ <dimen name="controls_header_horizontal_padding">12dp</dimen>
+ <dimen name="controls_content_margin_horizontal">24dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml b/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml
index b98165fb08f0..ca62d286f4ee 100644
--- a/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml
@@ -21,6 +21,6 @@
<!-- Space between status view and notification shelf -->
<dimen name="keyguard_status_view_bottom_margin">70dp</dimen>
<dimen name="keyguard_clock_top_margin">80dp</dimen>
- <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">186dp</dimen>
- <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">110dp</dimen>
+ <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">155dp</dimen>
+ <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">85dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
index 9ed936050aa2..8583f0549960 100644
--- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
@@ -37,6 +37,8 @@
<dimen name="qs_media_rec_album_size">112dp</dimen>
<dimen name="qs_media_rec_album_side_margin">16dp</dimen>
+ <dimen name="controls_panel_corner_radius">40dp</dimen>
+
<dimen name="lockscreen_shade_max_over_scroll_amount">42dp</dimen>
<!-- Roughly the same distance as media on LS to media on QS. We will translate by this value
diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
index 8b41a44b9ba3..9248d585bba7 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
@@ -33,5 +33,7 @@
side -->
<dimen name="qs_tiles_page_horizontal_margin">60dp</dimen>
+ <dimen name="controls_panel_corner_radius">46dp</dimen>
+
<dimen name="notification_section_divider_height">16dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index 8f59df655c3a..20864591ae5a 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -19,7 +19,8 @@
<!-- gap on either side of status bar notification icons -->
<dimen name="status_bar_icon_padding">1dp</dimen>
- <dimen name="controls_padding_horizontal">40dp</dimen>
+ <dimen name="controls_header_horizontal_padding">28dp</dimen>
+ <dimen name="controls_content_margin_horizontal">40dp</dimen>
<dimen name="large_screen_shade_header_height">56dp</dimen>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index e58acfa56c6d..0ea32b9afee9 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"அடுத்த முறை தவறான பின்னை உள்ளிட்டால் உங்கள் பணிக் கணக்கும் அதன் தரவும் நீக்கப்படும்."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"அடுத்த முறை தவறான கடவுச்சொல்லை உள்ளிட்டால் உங்கள் பணிக் கணக்கும் அதன் தரவும் நீக்கப்படும்."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"கைரேகை சென்சாரைத் தொடவும்"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"கைரேகை ஐகான்"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"முகத்தை அடையாளம் காண முடியவில்லை. கைரேகையைப் பயன்படுத்தவும்."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"பணி லாக் ஸ்கிரீன்"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"மூடு"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ஒளிர்வு"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"கலர் இன்வெர்ஷன்"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"கலர் கரெக்‌ஷன்"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"எழுத்து வடிவத்தின் அளவு"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"பயனர்களை நிர்வகியுங்கள்"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"முடிந்தது"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"மூடுக"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ஸ்கிரீன் ரெக்கார்டிங்"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"தலைப்பு இல்லை"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"இயக்க நேரம்"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"எழுத்து வடிவத்தின் அளவு"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"சிறிதாக்கும்"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"பெரிதாக்கும்"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"பெரிதாக்கல் சாளரம்"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"பெரிதாக்கல் சாளரக் கட்டுப்பாடுகள்"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"பெரிதாக்கு"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# கட்டுப்பாடு சேர்க்கப்பட்டது.}other{# கட்டுப்பாடுகள் சேர்க்கப்பட்டன.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"அகற்றப்பட்டது"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ஆப்ஸைச் சேர்க்கவா?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"இந்தப் பேனலில் <xliff:g id="APPNAME">%s</xliff:g> ஆப்ஸைச் சேர்க்கும்போது கட்டுப்பாடுகளையும் உள்ளடக்கத்தையும் அது சேர்க்கலாம். இருப்பினும், சில ஆப்ஸில் எந்தெந்தக் கட்டுப்பாடுகள் இங்கே காட்டப்பட வேண்டும் என்பதை நீங்களே தேர்வுசெய்யலாம்."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> ஆப்ஸுக்கான கட்டுப்பாடுகளை அகற்றவா?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"பிடித்தவற்றில் சேர்க்கப்பட்டது"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"பிடித்தவற்றில் சேர்க்கப்பட்டது, நிலை <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"பிடித்தவற்றிலிருந்து நீக்கப்பட்டது"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"பிற"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"சாதனக் கட்டுப்பாடுகளில் சேர்த்தல்"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"சேர்"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"அகற்று"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ஆப்ஸால் பரிந்துரைக்கப்பட்டது"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"சாதனம் பூட்டப்பட்டது"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"பூட்டுத் திரையிலிருந்தே சாதனங்களைப் பார்க்கவும் கட்டுப்படுத்தவும் அனுமதிக்கவா?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"வெளிப்புறச் சாதனங்களுக்கான கட்டுப்பாடுகளை உங்கள் பூட்டுத் திரையில் சேர்க்கலாம்.\n\nஉங்கள் மொபைலையோ டேப்லெட்டையோ அன்லாக் செய்யாமலேயே சில சாதனங்களைக் கட்டுப்படுத்த சாதன ஆப்ஸ் உங்களை அனுமதிக்கக்கூடும்.\n\nஅமைப்புகளுக்குச் சென்று எப்போது வேண்டுமானாலும் மாற்றங்களைச் செய்யலாம்."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"பூட்டுத் திரையிலிருந்தே சாதனங்களைக் கட்டுப்படுத்தவா?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"உங்கள் மொபைலையோ டேப்லெட்டையோ அன்லாக் செய்யாமலேயே சில சாதனங்களை நீங்கள் கட்டுப்படுத்தலாம்.\n\nஎந்தெந்தச் சாதனங்களை இவ்வாறு கட்டுப்படுத்தலாம் என்பதை உங்கள் சாதன ஆப்ஸ் தீர்மானிக்கும்."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"வேண்டாம்"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ஆம்"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"பின்னில் எழுத்துகள் அல்லது குறிகள் உள்ளன"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"கட்டுப்பாடுகளைச் சேர்த்தல்"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"கட்டுப்பாடுகளை மாற்றுதல்"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"ஆப்ஸைச் சேர்"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"ஆப்ஸை அகற்று"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"அவுட்புட்களைச் சேர்த்தல்"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"குழு"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 சாதனம் தேர்ந்தெடுக்கப்பட்டுள்ளது"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ஒளிபரப்ப முடியவில்லை"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"சேமிக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"சேமிக்க முடியவில்லை."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"குறைந்தது 4 எழுத்துகளைப் பயன்படுத்துங்கள்"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 எழுத்துகளுக்குக் குறைவாகப் பயன்படுத்துங்கள்"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• குறைந்தபட்சம் ஒரு சாதனமாவது கிடைக்க வேண்டும்"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ஷார்ட்கட்டை தொட்டுப் பிடிக்கவும்"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ரத்துசெய்"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"இப்போது திரைகளை மாற்றவா?"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"மொபைலை விரியுங்கள்"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"காட்சித் திரைகளை மாற்றுவது எப்படி?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"உயர் தெளிவுத்திறனுக்கு, பின்புறக் கேமராவை உபயோகிங்கள்"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"உயர் தெளிவுத்திறனுக்கு, மொபைலை ஃபிளிப் செய்யுங்கள்"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"மடக்கத்தக்க சாதனம் திறக்கப்படுகிறது"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"மடக்கத்தக்க சாதனம் ஃபிளிப் செய்யப்பட்டு திருப்பப்படுகிறது"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> பேட்டரி மீதமுள்ளது"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"பணிக் கணக்கிற்கு மாறு"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"மூடுக"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"பூட்டுத் திரை அமைப்புகள்"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"வைஃபை கிடைக்கவில்லை"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"கேமரா தடுக்கப்பட்டுள்ளது"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"கேமராவும் மைக்ரோஃபோனும் தடுக்கப்பட்டுள்ளன"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"மைக்ரோஃபோன் தடுக்கப்பட்டுள்ளது"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"முன்னுரிமைப் பயன்முறை இயக்கத்தில் உள்ளது"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta/tiles_states_strings.xml b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
index 1a22d9fa1476..5bcc6c761e1c 100644
--- a/packages/SystemUI/res/values-ta/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"முடக்கப்பட்டுள்ளது"</item>
<item msgid="5966994759929723339">"இயக்கப்பட்டுள்ளது"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"கிடைக்கவில்லை"</item>
+ <item msgid="2478289035899842865">"முடக்கப்பட்டுள்ளது"</item>
+ <item msgid="5137565285664080143">"இயக்கப்பட்டுள்ளது"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 11f528a1cc25..a7b493b33be3 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు పిన్‌ను ఎంటర్ చేస్తే, మీ కార్యాలయ ప్రొఫైల్, అలాగే దాని డేటా తొలగించబడతాయి."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు పాస్‌వర్డ్‌ను ఎంటర్ చేస్తే, మీ కార్యాలయ ప్రొఫైల్, అలాగే దాని డేటా తొలగించబడతాయి."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"వేలిముద్ర సెన్సార్‌ను తాకండి"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"వేలిముద్ర చిహ్నం"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ముఖం గుర్తించలేము. బదులుగా వేలిముద్ర ఉపయోగించండి."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"కార్యాలయ లాక్ స్క్రీన్"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"మూసివేస్తుంది"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ప్రకాశం"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"కలర్ మార్పిడి"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"కలర్ కరెక్షన్"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ఫాంట్ సైజ్"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"యూజర్‌లను మేనేజ్ చేయండి"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"పూర్తయింది"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"మూసివేయి"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"స్క్రీన్ రికార్డింగ్"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"శీర్షిక లేదు"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"స్టాండ్‌బై"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ఫాంట్ సైజ్"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"చిన్నదిగా చేస్తుంది"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"పెద్దదిగా చేస్తుంది"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"మ్యాగ్నిఫికేషన్ విండో"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"మ్యాగ్నిఫికేషన్ నియంత్రణల విండో"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"దగ్గరగా జూమ్ చేయండి"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# కంట్రోల్ జోడించబడింది.}other{# కంట్రోల్స్ జోడించబడ్డాయి.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"తీసివేయబడింది"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>ను జోడించాలా?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"మీరు <xliff:g id="APPNAME">%s</xliff:g>ను జోడించినప్పుడు, ఇది ఈ ప్యానెల్‌కు కంట్రోల్స్‌ని, కంటెంట్‌ను జోడించగలదు. కొన్ని యాప్‌లలో, ఇక్కడ ఏయే కంట్రోల్స్ కనిపించాలో మీరు ఎంచుకోవచ్చు."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> కోసం కంట్రోల్స్‌ను తీసివేయాలా?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"ఇష్టమైనదిగా గుర్తు పెట్టబడింది"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>వ స్థానంలో ఇష్టమైనదిగా గుర్తు పెట్టబడింది"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ఇష్టమైనదిగా పెట్టిన గుర్తు తీసివేయబడింది"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ఇతరం"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"పరికరం నియంత్రణలకు జోడించడం"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"జోడించండి"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"తీసివేయండి"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ద్వారా సూచించబడింది"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"పరికరంలాక్ చేయబడింది"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"లాక్ స్క్రీన్ నుండి పరికరాలను చూపించాలా, కంట్రోల్ చేయాలా?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"మీరు లాక్ స్క్రీన్‌కు మీ బాహ్య పరికరాల కోసం కంట్రోల్స్‌ను జోడించవచ్చు.\n\nమీ ఫోన్ లేదా టాబ్లెట్‌ను అన్‌లాక్ చేయకుండానే కొన్ని పరికరాలను కంట్రోల్ చేయడానికి మీ పరికర యాప్ మిమ్మల్ని అనుమతించవచ్చు.\n\nమీరు సెట్టింగ్‌లలో ఎప్పుడైనా మార్పులు చేయవచ్చు."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"లాక్ స్క్రీన్ నుండి పరికరాలను కంట్రోల్ చేయాలా?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"మీరు మీ ఫోన్ లేదా టాబ్లెట్‌ను అన్‌లాక్ చేయకుండానే కొన్ని పరికరాలను కంట్రోల్ చేయవచ్చు.\n\nమీ పరికర యాప్ \'ఈ విధంగా ఏ పరికరాలను కంట్రోల్ చేయవచ్చు\' అని నిర్ణయిస్తుంది."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"వద్దు, ధన్యవాదాలు"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"అవును"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"పిన్ అక్షరాలను లేదా చిహ్నాలను కలిగి ఉంది"</string>
@@ -876,12 +876,13 @@
<string name="controls_error_removed" msgid="6675638069846014366">"కనుగొనబడలేదు"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"కంట్రోల్ అందుబాటులో లేదు"</string>
<string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>ను యాక్సెస్ చేయడం సాధ్యపడలేదు. <xliff:g id="APPLICATION">%2$s</xliff:g> యాప్‌ను చెక్ చేసి, కంట్రోల్ ఇప్పటికీ అందుబాటులో ఉందని, యాప్ సెట్టింగ్‌లు మారలేదని నిర్ధారించుకోండి."</string>
- <string name="controls_open_app" msgid="483650971094300141">"యాప్‌ను తెరువు"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"యాప్‌‌ను తెరవండి"</string>
<string name="controls_error_generic" msgid="352500456918362905">"స్టేటస్ లోడ్ చేయడం సాధ్యపడలేదు"</string>
<string name="controls_error_failed" msgid="960228639198558525">"ఎర్రర్, మళ్లీ ప్రయత్నించండి"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"కంట్రోల్స్‌ను జోడించండి"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"కంట్రోల్స్‌ను ఎడిట్ చేయండి"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"యాప్‌ను జోడించండి"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"యాప్‌ను తీసివేయండి"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"అవుట్‌పుట్‌లను జోడించండి"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"గ్రూప్"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 పరికరం ఎంచుకోబడింది"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• కనీసం ఒక పరికరమైనా అందుబాటులో ఉందని"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"షార్ట్‌కట్‌ను తాకి, నొక్కి ఉంచు"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"రద్దు చేయండి"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ఇప్పుడే స్క్రీన్‌లను మార్చండి"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ఫోన్‌ను అన్‌ఫోల్డ్ చేయండి"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"స్క్రీన్‌లను మార్చాలా?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"అధిక రిజల్యూషన్ కోసం, వెనుక వైపు కెమెరాను ఉపయోగించండి"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"అధిక రిజల్యూషన్ కోసం, ఫోన్‌ను తిప్పండి"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"మడవగల పరికరం విప్పబడుతోంది"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"మడవగల పరికరం చుట్టూ తిప్పబడుతోంది"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> బ్యాటరీ మిగిలి ఉంది"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"వర్క్ ప్రొఫైల్‌కు మారండి"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"మూసివేయండి"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"లాక్ స్క్రీన్ సెట్టింగ్‌లు"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi అందుబాటులో లేదు"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"కెమెరా బ్లాక్ చేయబడింది"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"కెమెరా, మైక్రోఫోన్ బ్లాక్ చేయబడ్డాయి"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"మైక్రోఫోన్ బ్లాక్ చేయబడింది"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ప్రయారిటీ మోడ్ ఆన్‌లో ఉంది"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/tiles_states_strings.xml b/packages/SystemUI/res/values-te/tiles_states_strings.xml
index c5a525cb611f..6549c5631161 100644
--- a/packages/SystemUI/res/values-te/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-te/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"ఆఫ్"</item>
<item msgid="5966994759929723339">"ఆన్"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"అందుబాటులో లేదు"</item>
+ <item msgid="2478289035899842865">"ఆఫ్‌లో ఉంది"</item>
+ <item msgid="5137565285664080143">"ఆన్‌లో ఉంది"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index c3037be4ea6f..4513564b2afd 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"หากคุณป้อน PIN ไม่ถูกต้องในความพยายามครั้งถัดไป ระบบจะลบโปรไฟล์งานและข้อมูลในโปรไฟล์"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"หากคุณป้อนรหัสผ่านไม่ถูกต้องในความพยายามครั้งถัดไป ระบบจะลบโปรไฟล์งานและข้อมูลในโปรไฟล์"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"แตะเซ็นเซอร์ลายนิ้วมือ"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ไอคอนลายนิ้วมือ"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ไม่รู้จักใบหน้า ใช้ลายนิ้วมือแทน"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"หน้าจอล็อกของโปรไฟล์งาน"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ปิด"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ความสว่าง"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"การกลับสี"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"การแก้สี"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ขนาดแบบอักษร"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"จัดการผู้ใช้"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"เสร็จสิ้น"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ปิด"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"การบันทึกหน้าจอ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ไม่มีชื่อ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"สแตนด์บาย"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ขนาดแบบอักษร"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ทำให้เล็กลง"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ทำให้ใหญ่ขึ้น"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"หน้าต่างการขยาย"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"การควบคุมหน้าต่างการขยาย"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ซูมเข้า"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{เพิ่มตัวควบคุม # ตัวแล้ว}other{เพิ่มตัวควบคุม # ตัวแล้ว}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"นำออกแล้ว"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"เพิ่ม <xliff:g id="APPNAME">%s</xliff:g> ไหม"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"เมื่อเพิ่ม <xliff:g id="APPNAME">%s</xliff:g> คุณจะเพิ่มการควบคุมและเนื้อหาไปยังแผงนี้ได้ ในบางแอป คุณเลือกได้ว่าต้องการให้การควบคุมใดปรากฏขึ้นที่นี่"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"นำการควบคุมสำหรับ <xliff:g id="APPNAME">%s</xliff:g> ออกไหม"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"ตั้งเป็นรายการโปรดแล้ว"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"ตั้งเป็นรายการโปรดแล้ว โดยอยู่ลำดับที่ <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"นำออกจากรายการโปรดแล้ว"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"อื่นๆ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"เพิ่มไปยังระบบควบคุมอุปกรณ์"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"เพิ่ม"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"นำออก"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"แนะนำโดย <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"อุปกรณ์ถูกล็อก"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"แสดงและควบคุมอุปกรณ์จากหน้าจอล็อกไหม"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"คุณเพิ่มการควบคุมอุปกรณ์ภายนอกลงในหน้าจอล็อกได้\n\nแอปของอุปกรณ์อาจอนุญาตให้คุณควบคุมอุปกรณ์บางอย่างได้โดยไม่ต้องปลดล็อกโทรศัพท์หรือแท็บเล็ต\n\nคุณเปลี่ยนแปลงได้ทุกเมื่อในการตั้งค่า"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ควบคุมอุปกรณ์จากหน้าจอล็อกไหม"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"คุณควบคุมอุปกรณ์บางอย่างได้โดยไม่ต้องปลดล็อกโทรศัพท์หรือแท็บเล็ต\n\nแอปของอุปกรณ์จะระบุอุปกรณ์ที่สามารถควบคุมด้วยวิธีนี้ได้"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ไม่เป็นไร"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"มี"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ประกอบด้วยตัวอักษรหรือสัญลักษณ์"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"เพิ่มตัวควบคุม"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"แก้ไขตัวควบคุม"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"เพิ่มแอป"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"นำแอปออก"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"เพิ่มเอาต์พุต"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"กลุ่ม"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"เลือกอุปกรณ์ไว้ 1 รายการ"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• มีอุปกรณ์พร้อมใช้งานอย่างน้อย 1 รายการ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"แตะแป้นพิมพ์ลัดค้างไว้"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ยกเลิก"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"สลับหน้าจอเลย"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"กางโทรศัพท์ออก"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"สลับหน้าจอไหม"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ใช้กล้องหลังเพื่อให้ได้ภาพที่มีความละเอียดมากขึ้น"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"พลิกด้านโทรศัพท์เพื่อให้ได้ภาพที่มีความละเอียดมากขึ้น"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"อุปกรณ์ที่พับได้กำลังกางออก"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"อุปกรณ์ที่พับได้กำลังพลิกไปมา"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"เหลือแบตเตอรี่ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"สลับไปใช้โปรไฟล์งาน"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ปิด"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"การตั้งค่าหน้าจอล็อก"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ไม่พร้อมใช้งาน"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"กล้องถูกบล็อกอยู่"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"กล้องและไมโครโฟนถูกบล็อกอยู่"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ไมโครโฟนถูกบล็อกอยู่"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"โหมดลำดับความสำคัญเปิดอยู่"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/tiles_states_strings.xml b/packages/SystemUI/res/values-th/tiles_states_strings.xml
index 61e0fe6bde77..69449a72196e 100644
--- a/packages/SystemUI/res/values-th/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-th/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"ปิด"</item>
<item msgid="5966994759929723339">"เปิด"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ไม่พร้อมใช้งาน"</item>
+ <item msgid="2478289035899842865">"ปิด"</item>
+ <item msgid="5137565285664080143">"เปิด"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index c991c82eb936..d75b992141e5 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Kung maling PIN ang mailalagay mo sa susunod na pagsubok, made-delete ang iyong profile sa trabaho at ang data nito."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Kung maling password ang mailalagay mo sa susunod na pagsubok, made-delete ang iyong profile sa trabaho at ang data nito."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Pindutin ang fingerprint sensor"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icon ng fingerprint"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Hindi makilala ang mukha. Gumamit ng fingerprint."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mga mabilisang setting."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Mga mabilisang setting at Notification shade."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Lock screen sa trabaho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Isara"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brightness"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Pag-invert ng kulay"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Pagtatama ng kulay"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Laki ng font"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Pamahalaan ang mga user"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Tapos na"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Isara"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"pag-record ng screen"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Walang pamagat"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Naka-standby"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Laki ng Font"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Paliitin"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Palakihin"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Window ng Pag-magnify"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Mga Kontrol sa Pag-magnify ng Window"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Mag-zoom in"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Nagdagdag ng # kontrol.}one{Nagdagdag ng # kontrol.}other{Nagdagdag ng # na kontrol.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Inalis"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Idagdag ang <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Kapag idinagdag mo ang <xliff:g id="APPNAME">%s</xliff:g>, puwede itong magdagdag ng mga kontrol at content sa panel na ito. Sa ilang app, puwede mong piliin kung aling mga kontrol ang lalabas dito."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Alisin ang mga kontrol para sa <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Ginawang paborito"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ginawang paborito, posisyon <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Inalis sa paborito"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Iba pa"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Idagdag sa mga kontrol ng device"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Idagdag"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Alisin"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Iminungkahi ng <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Naka-lock ang device"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Ipakita at kontrolin ang mga device mula sa lock screen?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Puwede kang magdagdag ng mga kontrol para sa iyong mga external device sa lock screen.\n\nPosibleng payagan ka ng app ng iyong device na kontrolin ang ilang device nang hindi ina-unlock ang telepono o tablet mo.\n\nPuwede kang magsagawa ng mga pagbabago anumang oras sa Mga Setting."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Kontrolin ang mga device mula sa lock screen?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Puwede mong kontrolin ang ilang device nang hindi ina-unlock ang iyong telepono o tablet.\n\nNakadepende sa app ng iyong device kung aling mga device ang puwedeng kontrolin sa ganitong paraan."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Huwag na lang"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Oo"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"May mga titik o simbolo ang PIN"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Magdagdag ng mga kontrol"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Mag-edit ng mga kontrol"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Magdagdag ng app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Alisin ang app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Magdagdag ng mga output"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 device ang napili"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Hindi makapag-broadcast"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gumamit ng hindi bababa sa 4 na character"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gumamit ng mas kaunti sa 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• May kahit isang device na available"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Lumipat na ng screen"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"I-unfold ang telepono"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Lumipat ng screen?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para sa mas mataas na resolution, gamitin ang camera sa likod"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para sa mas mataas na resolution, i-flip ang telepono"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ina-unfold na foldable na device"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Fini-flip na foldable na device"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> baterya na lang ang natitira"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Lumipat sa profile sa trabaho"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Isara"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Mga setting ng lock screen"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Hindi available ang Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Naka-block ang camera"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Naka-block ang camera at mikropono"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Naka-block ang mikropono"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Naka-on ang Priority mode"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/tiles_states_strings.xml b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
index 4522945908c9..689c2a26ca61 100644
--- a/packages/SystemUI/res/values-tl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Naka-off"</item>
<item msgid="5966994759929723339">"Naka-on"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Hindi available"</item>
+ <item msgid="2478289035899842865">"Naka-off"</item>
+ <item msgid="5137565285664080143">"Naka-on"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index d8569b32b1b2..4321894b7f23 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Bir sonraki denemenizde yanlış PIN girerseniz iş profiliniz ve verileri silinir."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Bir sonraki denemenizde yanlış şifre girerseniz iş profiliniz ve verileri silinir."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Parmak izi sensörüne dokunun"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Parmak izi simgesi"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Yüz tanınamadı. Bunun yerine parmak izi kullanın."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildirim gölgesi."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hızlı ayarlar."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hızlı ayarlar ve Bildirim gölgesi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kilit ekranı"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"İş profili kilit ekranı"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Kapat"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Parlaklık"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Rengi ters çevirme"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Renk düzeltme"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Yazı tipi boyutu"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Kullanıcıları yönet"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Bitti"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Kapat"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekran kaydı"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Başlıksız"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Beklemeye alınıyor"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Yazı Tipi Boyutu"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Küçült"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Büyüt"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Büyütme Penceresi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Büyütme Penceresi Kontrolleri"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Yakınlaştır"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrol eklendi.}other{# kontrol eklendi.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Kaldırıldı"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> eklensin mi?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> uygulamasını eklerseniz bu panele kontrol ve içerik ekleyebilir. Bazı uygulamalarda, burada hangi kontrollerin görüneceğini seçebilirsiniz."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> için denetimler kaldırılsın mı?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Favoriler listesine eklendi"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favorilere eklendi, konum: <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Favorilerden kaldırıldı"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Diğer"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Cihaz denetimlerine ekle"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Ekle"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Kaldır"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> tarafından önerildi"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Cihaz kilitlendi"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Cihazlar kilit ekranında gösterilip buradan kontrol edilsin mi?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Kilit ekranına harici cihazlarınız için kontroller ekleyebilirsiniz.\n\nCihaz uygulamanız, bazı cihazları telefonunuzun veya tabletinizin kilidini açmadan kontrol etmenize izin verebilir.\n\nAyarlar\'da istediğiniz zaman değişiklik yapabilirsiniz."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Cihazlar kilit ekranından kontrol edilsin mi?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Bazı cihazları telefonunuzun veya tabletinizin kilidini açmadan kontrol edebilirsiniz.\n\nHangi cihazların bu şekilde kontrol edilebileceğini cihaz uygulamanız belirler."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Hayır, teşekkürler"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Evet"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN, harf veya simge içerir"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Denetim ekle"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Denetimleri düzenle"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Uygulama ekle"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Uygulamayı kaldır"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Çıkışlar ekleyin"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçildi"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Yayınlanamıyor"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"En az 4 karakter kullanın."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"En fazla 16 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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• En az bir cihaz mevcut olmalıdır"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Ekranı şimdi değiştirin"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Telefonu açın"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Ekran değiştirilsin mi?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Daha yüksek çözünürlük için arka kamerayı kullanın"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Daha yüksek çözünürlük için telefonu çevirin"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Katlanabilir cihaz açılıyor"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Katlanabilir cihaz döndürülüyor"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> pil kaldı"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"İş profiline geç"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Kapat"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Kilit ekranı ayarları"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Kablosuz bağlantı kullanılamıyor"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera engellendi"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera ve mikrofon engellendi"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon engellendi"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Öncelik modu etkin"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/tiles_states_strings.xml b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
index 5d6a7f429614..a8c7f784920d 100644
--- a/packages/SystemUI/res/values-tr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Kapalı"</item>
<item msgid="5966994759929723339">"Açık"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Kullanılamıyor"</item>
+ <item msgid="2478289035899842865">"Kapalı"</item>
+ <item msgid="5137565285664080143">"Açık"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index df1d27a5aa38..b499240f33b1 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Якщо наступного разу ви введете неправильний PIN-код, ваш робочий профіль і його дані буде видалено."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Якщо наступного разу ви введете неправильний пароль, ваш робочий профіль і його дані буде видалено."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Торкніться сканера відбитків пальців"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Значок відбитка пальця"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Обличчя не розпізнано. Скористайтеся відбитком пальця."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Екран блокування завдання"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Закрити"</string>
@@ -233,7 +233,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Джерело сигналу"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Слухові апарати"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Увімкнення…"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Автоматичне обертання"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Автообертання"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Автоматично обертати екран"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Геодані"</string>
<string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Заставка"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яскравість"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Інверсія кольорів"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекція кольору"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Розмір шрифту"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Керувати користувачами"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Готово"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Закрити"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"запис відео з екрана"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без назви"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Режим очікування"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Розмір шрифту"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Зменшити"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Збільшити"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Вікно збільшення"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Елементи керування вікна збільшення"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Наблизити"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Додано # елемент керування.}one{Додано # елемент керування.}few{Додано # елементи керування.}many{Додано # елементів керування.}other{Додано # елемента керування.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Вилучено"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Долучити додаток <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Якщо ви долучите додаток <xliff:g id="APPNAME">%s</xliff:g>, він зможе розміщувати елементи керування й контент на цій панелі. У деяких додатках можна вибрати, які елементи керування тут відображатимуться."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Вилучити елементи керування для додатка <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Додано у вибране"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Додано у вибране, позиція <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Видалено з вибраного"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Інше"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Додати до елементів керування пристроями"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Додати"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Вилучити"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Запропоновано додатком <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Пристрій заблоковано"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Переглядати пристрої та керувати ними на заблокованому екрані?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Елементи керування зовнішніми пристроями можна додавати на заблокований екран.\n\nЗа допомогою спеціального додатка ви можете керувати деякими пристроями, не розблоковуючи телефон або планшет.\n\nВи можете будь-коли вносити зміни в налаштуваннях."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Керувати пристроями на заблокованому екрані?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Ви можете керувати деякими пристроями, не розблоковуючи телефон або планшет.\n\nЯкими пристроями можна керувати в такий спосіб, визначає додаток на пристрої."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ні, дякую"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Так"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-код містить літери чи символи"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Додати елементи керування"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Змінити елементи керування"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Долучити додаток"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Вилучити додаток"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Додати пристрої виводу"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Вибрано 1 пристрій"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Неможливо транслювати"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не вдалося зберегти. Повторіть спробу."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не вдалося зберегти."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Введіть принаймні 4 символи"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Введіть менше ніж 16 символів"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Принаймні один пристрій доступний"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Натисніть і утримуйте ярлик"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Скасувати"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Використовувати інший екран"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Розгорніть телефон"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Використовувати інший екран?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Для вищої роздільної здатності використовуйте основну камеру"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Для вищої роздільної здатності переверніть телефон"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Розкладний пристрій у розкладеному стані"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Розкладний пристрій обертається"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Заряд акумулятора: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Перейти в робочий профіль"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрити"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Параметри заблокованого екрана"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Мережа Wi-Fi недоступна"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камеру заблоковано"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камеру й мікрофон заблоковано"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрофон заблоковано"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Режим пріоритету ввімкнено"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/tiles_states_strings.xml b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
index a0cc1c19d46d..4062f1be4c08 100644
--- a/packages/SystemUI/res/values-uk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Вимкнено"</item>
<item msgid="5966994759929723339">"Увімкнено"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Недоступно"</item>
+ <item msgid="2478289035899842865">"Вимкнено"</item>
+ <item msgid="5137565285664080143">"Увімкнено"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 089e4b476843..42ef9cdac27b 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -93,8 +93,8 @@
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"دایاں احاطہ <xliff:g id="PERCENT">%1$d</xliff:g> فیصد"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"دفتری پروفائل میں <xliff:g id="APP">%1$s</xliff:g> میں محفوظ کی گئی"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"فائلز"</string>
- <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
- <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> اور دیگر کھلی ایپس نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
+ <string name="screenshot_detected_template" msgid="7940376642921719915">"‫<xliff:g id="APPNAME">%1$s</xliff:g> نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
+ <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"‫<xliff:g id="APPNAME">%1$s</xliff:g> اور دیگر کھلی ایپس نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"اسکرین ریکارڈر"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"سکرین ریکارڈنگ پروسیس ہورہی ہے"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string>
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"‏اگر آپ نے اگلی کوشش میں غلط PIN درج کیا تو آپ کی دفتری پروفائل اور اس کا ڈیٹا حذف کر دیا جائے گا۔"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"اگر آپ نے اگلی کوشش میں غلط پاس ورڈ درج کیا تو آپ کی دفتری پروفائل اور اس کا ڈیٹا حذف کر دیا جائے گا۔"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"فنگر پرنٹ سینسر پر ٹچ کریں"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"فنگر پرنٹ آئیکن"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"چہرے کی شناخت نہیں ہو سکی۔ اس کے بجائے فنگر پرنٹ استعمال کریں۔"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -187,8 +186,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"بیٹری <xliff:g id="NUMBER">%d</xliff:g> فیصد۔"</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"بیٹری <xliff:g id="PERCENTAGE">%1$d</xliff:g> فیصد ہے، <xliff:g id="TIME">%2$s</xliff:g> تک چلے گی"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"بیٹری چارج ہو رہی ہے، اس وقت <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> فیصد ہے۔"</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"بیٹری <xliff:g id="PERCENTAGE">%d</xliff:g> فیصد پے، بیٹری کے تحفظ کے لیے چارجنگ موقوف ہو گئی ہے۔"</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"بیٹری <xliff:g id="PERCENTAGE">%1$d</xliff:g> فیصد پے، <xliff:g id="TIME">%2$s</xliff:g> تک چلے گی، بیٹری کے تحفظ کے لیے چارجنگ موقوف ہو گئی ہے۔"</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"بیٹری <xliff:g id="PERCENTAGE">%d</xliff:g> فیصد، بیٹری کے تحفظ کے لیے چارجنگ موقوف ہو گئی ہے۔"</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"بیٹری <xliff:g id="PERCENTAGE">%1$d</xliff:g> فیصد، <xliff:g id="TIME">%2$s</xliff:g>، بیٹری کے تحفظ کے لیے چارجنگ موقوف ہو گئی ہے۔"</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"تمام اطلاعات دیکھیں"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"ٹیلی ٹائپ رائٹر فعال ہے۔"</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"رنگر وائبریٹ۔"</string>
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"دفتری مقفل اسکرین"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"بند کریں"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"چمکیلا پن"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"رنگوں کی تقلیب"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"رنگ کی اصلاح"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"فونٹ سائز"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"صارفین کا نظم کریں"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ہو گیا"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"بند کریں"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"اسکرین ریکارڈنگ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"کوئی عنوان نہیں ہے"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"اسٹینڈ بائی"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"فونٹ سائز"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"چھوٹا کریں"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"بڑا کریں"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"میگنیفکیشن ونڈو"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"میگنیفکیشن ونڈو کنٹرولز"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"زوم ان کریں"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# کنٹرول کو شامل کیا گیا۔}other{# کنٹرولز کو شامل کیا گیا۔}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"ہٹا دیا گیا"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> کو شامل کریں؟"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"جب آپ <xliff:g id="APPNAME">%s</xliff:g> کو شامل کرتے ہیں، تو یہ اس پینل میں کنٹرولز اور مواد کو شامل کر سکتا ہے۔ کچھ ایپس میں، آپ یہ منتخب کر سکتے ہیں کہ کون سے کنٹرولز یہاں ظاہر ہوں۔"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> کے کنٹرولز کو ہٹا دیں؟"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"پسند کردہ"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"پسند کردہ، پوزیشن <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ناپسند کردہ"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"دیگر"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"آلہ کے کنٹرولز میں شامل کریں"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"شامل کریں"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"ہٹائیں"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> کی طرف سے تجویز کردہ"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"آلہ مقفل کر دیا گیا"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"لاک اسکرین سے آلات دکھائیں اور کنٹرول کریں؟"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"آپ اپنے بیرونی آلات کے لیے لاک اسکرین پر کنٹرولز شامل کر سکتے ہیں۔\n\nآپ کے آلے کی ایپ آپ کو اپنے فون یا ٹیبلیٹ کو غیر مقفل کیے بغیر کچھ آلات کو کنٹرول کرنے کی اجازت دے سکتی ہے۔\n\nآپ ترتیبات میں کسی بھی وقت تبدیلیاں کر سکتے ہیں۔"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"لاک اسکرین سے آلات کو کنٹرول کریں؟"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"آپ اپنے فون یا ٹیبلیٹ کو غیر مقفل کیے بغیر کچھ آلات کو کنٹرول کر سکتے ہیں۔\n\nآپ کے آلے کی ایپ اس بات کا تعین کرتی ہے کہ اس طرح کن آلات کو کنٹرول کیا جا سکتا ہے۔"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"نہیں شکریہ"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ہاں"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"‏PIN میں حروف یا علامات شامل ہیں"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"کنٹرولز شامل کریں"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"کنٹرولز میں ترمیم کریں"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"ایپ شامل کریں"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"ایپ ہٹائیں"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"آؤٹ پٹس شامل کریں"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"گروپ"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 آلہ منتخب کیا گیا"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"براڈکاسٹ نہیں کیا جا سکتا"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"محفوظ نہیں کیا جا سکا۔ پھر کوشش کریں۔"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"محفوظ نہیں کیا جا سکا۔"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"کم از کم 4 حروف استعمال کریں"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 حروف سے کم استعمال کریں"</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>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• کم از کم ایک آلہ دستیاب ہے"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"شارٹ کٹ ٹچ کریں اور دبائے رکھیں"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"منسوخ کریں"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"اب اسکرینز سوئچ کریں"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"فون کھولیں"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"اسکرینز سوئچ کریں؟"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"زیادہ ریزولوشن کے لیے، بَیک کیمرا استعمال کریں"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"زیادہ ریزولوشن کے لیے، فون پلٹائیں"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"فولڈ ہونے والے آلے کو کھولا جا رہا ہے"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"فولڈ ہونے والے آلے کو گھمایا جا رہا ہے"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> بیٹری باقی ہے"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"دفتری پروفائل پر سوئچ کریں"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"بند کریں"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"مقفل اسکرین کی ترتیبات"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏Wi-Fi دستیاب نہیں ہے"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"کیمرا مسدود ہے"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"کیمرا اور مائیکروفون مسدود ہے"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"مائیکروفون مسدود ہے"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ترجیحی موڈ آن ہے"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/tiles_states_strings.xml b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
index 5e2b0736ec8f..bb27b9fbe9f2 100644
--- a/packages/SystemUI/res/values-ur/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"آف"</item>
<item msgid="5966994759929723339">"آن"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"دستیاب نہیں ہیں"</item>
+ <item msgid="2478289035899842865">"آف ہے"</item>
+ <item msgid="5137565285664080143">"آن ہے"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 7df2aed28fff..98d92a95c83c 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -93,8 +93,8 @@
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Oʻng chegara <xliff:g id="PERCENT">%1$d</xliff:g> foiz"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Ish profilidagi <xliff:g id="APP">%1$s</xliff:g> ilovasiga saqlandi"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fayllar"</string>
- <string name="screenshot_detected_template" msgid="7940376642921719915">"Bu skrinshotda <xliff:g id="APPNAME">%1$s</xliff:g> aniqlandi."</string>
- <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Bu skrinshotda <xliff:g id="APPNAME">%1$s</xliff:g> va boshqa ochiq ilovalar aniqlandi"</string>
+ <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> skrinshot olinganini aniqladi."</string>
+ <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> va boshqa ochiq ilovalar skrinshot olinganini aniqladi."</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Ekrandan yozib olish"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran yozib olinmoqda"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekrandan yozib olish seansi uchun joriy bildirishnoma"</string>
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Agar PIN kodni xato kiritsangiz, ish profili va undagi maʼlumotlar oʻchirib tashlanadi."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Agar parolni xato kiritsangiz, ish profili va undagi maʼlumotlar oʻchirib tashlanadi."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Barmoq izi skaneriga tegining"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Barmoq izi belgisi"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Bu yuz notanish. Barmoq izi orqali urining."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -187,8 +186,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batareya <xliff:g id="NUMBER">%d</xliff:g> foiz."</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Batareya <xliff:g id="PERCENTAGE">%1$d</xliff:g> foiz, <xliff:g id="TIME">%2$s</xliff:g> yetadi."</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batareya quvvat olmoqda, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> foiz."</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Batareya <xliff:g id="PERCENTAGE">%d</xliff:g> foiz, batareya himoyasi uchun quvvatlash toʻxtatildi."</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Batareya <xliff:g id="PERCENTAGE">%1$d</xliff:g> foiz, <xliff:g id="TIME">%2$s</xliff:g> yetadi, batareya himoyasi uchun quvvatlash toʻxtatildi."</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Batareya <xliff:g id="PERCENTAGE">%d</xliff:g> foiz, batareya himoyasi uchun quvvatlash pauza qilindi."</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Batareya <xliff:g id="PERCENTAGE">%1$d</xliff:g> foiz, <xliff:g id="TIME">%2$s</xliff:g>, batareya himoyasi uchun quvvatlash pauza qilindi."</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"Barcha bildirishnomalarni ko‘rish"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter yoqildi."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibratsiyali qo‘ng‘iroq"</string>
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Xabarnoma soyasi."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tezkor sozlamalar."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Tezkor sozlamalar va eslatma soyasi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Qulflash ekrani."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ishchi ekran qulfi"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Yopish"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Yorqinlik"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ranglarni akslantirish"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Ranglarni tuzatish"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Shrift oʻlchami"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Foydalanuvchilarni boshqarish"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Tayyor"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Yopish"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekranni yozuvi"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nomsiz"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Kutib turing"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Shrift oʻlchami"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Kichiklashtirish"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Kattalashtirish"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Kattalashtirish oynasi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kattalashtirish oynasi sozlamalari"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Yaqinlashtirish"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ta boshqaruv elementi kiritildi.}other{# ta boshqaruv elementi kiritildi.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Olib tashlandi"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> qoʻshilsinmi?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> bu panelga boshqaruv elementlari va kontent qoʻshishi mumkin. Ayrim ilovalarda bu yerda qaysi elementlar chiqishini tanlashingiz mumkin."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> qurilma boshqaruv panelidan olib tashlansinmi?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Saralanganlarga kiritilgan"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Saralanganlarga kiritilgan, <xliff:g id="NUMBER">%d</xliff:g>-joy"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Saralanganlardan olib tashlangan"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Boshqa"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Qurilma boshqaruv elementlariga kiritish"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Kiritish"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Olib tashlash"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> taklif etgan"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Qurilma qulflandi"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Qurilmalar qulflangan ekranda koʻrsatilsinmi va boshqarilsinmi?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Tashqi qurilmalaringiz uchun ekran qulfiga boshqaruvlarni qoʻshishingiz mumkin.\n\nQurilma ilovasi ayrim qurilmalarni telefon yoki planshet qulfini ochmasdan boshqarish imkonini beradi.\n\nIstalgan vaqtda Sozlamalar orqali oʻzgartirish mumkin."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Qurilmalar ekran qulfidan boshqarilsinmi?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Ayrim qurilmalarni telefon yoki planshet ekran qulfini ochmasdan boshqarish mumkin.\n\nQurilmangiz ilovasi qaysi qurilmalarni shu tarzda boshqarish mumkinligini aniqlaydi."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Yopish"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ha"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Harflar yoki maxsus belgilardan iborat PIN kod"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Element kiritish"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Elementlarni tahrirlash"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ilova kiritish"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Ilovani olib tashlash"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Chiquvchi qurilmani kiritish"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Guruh"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ta qurilma tanlandi"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Kamida bitta qurilma mavjud"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Ekranlarni hozir almashtirish"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Telefonni yoying"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Ekranlar almashtirilsinmi?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Yuqori aniqlik uchun orqa kameradan foydalaning"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Yuqori aniqlik uchun telefonni aylantiring"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Buklanadigan qurilma ochilmoqda"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Buklanadigan qurilma aylantirilmoqda"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Batareya quvvati: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Ish profiliga almashish"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Yopish"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Qulflangan ekran sozlamalari"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi mavjud emas"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera bloklangan"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera va mikrofon bloklangan"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon bloklangan"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Imtiyozli rejim yoniq"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/tiles_states_strings.xml b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
index 6d55fc1f1225..4a45f03f4cbe 100644
--- a/packages/SystemUI/res/values-uz/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Oʻchiq"</item>
<item msgid="5966994759929723339">"Yoniq"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Mavjud emas"</item>
+ <item msgid="2478289035899842865">"Oʻchiq"</item>
+ <item msgid="5137565285664080143">"Yoniq"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index caeb44c5985e..d44848eda30c 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Nếu bạn nhập mã PIN không chính xác vào lần thử tiếp theo, thì hồ sơ công việc của bạn và dữ liệu của hồ sơ công việc sẽ bị xóa."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Nếu bạn nhập mật khẩu không chính xác vào lần thử tiếp theo, thì hồ sơ công việc của bạn và dữ liệu của hồ sơ công việc sẽ bị xóa."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Chạm vào cảm biến vân tay"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Biểu tượng vân tay"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Không thể nhận dạng khuôn mặt. Hãy dùng vân tay."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bóng thông báo."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Cài đặt nhanh."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Cài đặt nhanh và ngăn thông báo."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Màn hình khóa."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Màn hình khóa công việc"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Đóng"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Độ sáng"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Đảo màu"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Chỉnh màu"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Cỡ chữ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Quản lý người dùng"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Xong"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Đóng"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ghi màn hình"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Không có tiêu đề"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Chế độ chờ"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Cỡ chữ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Thu nhỏ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Phóng to"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Cửa sổ phóng to"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Các tùy chọn điều khiển cửa sổ phóng to"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Phóng to"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Đã thêm # chế độ điều khiển.}other{Đã thêm # chế độ điều khiển.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Đã xóa"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Thêm <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Khi bạn thêm <xliff:g id="APPNAME">%s</xliff:g>, ứng dụng có thể bổ sung các chế độ điều khiển và nội dung vào bảng điều khiển này. Trong một số ứng dụng, bạn có thể chọn chế độ điều khiển nào sẽ hiển thị tại đây."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Xoá chế độ cài đặt cho <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Được yêu thích"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Được yêu thích, vị trí số <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Không được yêu thích"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Khác"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Thêm vào mục điều khiển thiết bị"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Thêm"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Xoá"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Do <xliff:g id="APP">%s</xliff:g> đề xuất"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Đã khóa thiết bị"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Bạn muốn hiện và điều khiển các thiết bị từ màn hình khoá?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Bạn có thể thêm các chế độ điều khiển cho những thiết bị bên ngoài vào màn hình khoá.\n\nỨng dụng thiết bị có thể cho phép bạn điều khiển một số thiết bị mà không cần mở khoá điện thoại hoặc máy tính bảng.\n\nBạn có thể thay đổi chế độ cài đặt này bất cứ lúc nào trong phần Cài đặt."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Bạn muốn điều khiển các thiết bị từ màn hình khoá?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Bạn có thể điều khiển một số thiết bị mà không cần mở khoá điện thoại hoặc máy tính bảng.\n\nỨng dụng thiết bị sẽ xác định thiết bị mà bạn có thể điều khiển bằng cách này."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Không, cảm ơn"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Có"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Mã PIN chứa các ký tự hoặc ký hiệu"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Thêm các tùy chọn điều khiển"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Chỉnh sửa tùy chọn điều khiển"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Thêm ứng dụng"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Xoá ứng dụng"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Thêm thiết bị đầu ra"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Nhóm"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Đã chọn 1 thiết bị"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Không thể truyền"</string>
<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>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Sử dụng ít nhất 4 ký tự"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Sử dụng ít hơn 16 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>
@@ -1032,16 +1031,11 @@
<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_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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Chuyển đổi màn hình ngay"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Mở điện thoại"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Chuyển đổi màn hình?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Để có độ phân giải cao hơn, hãy dùng máy ảnh sau"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Để có độ phân giải cao hơn, hãy lật điện thoại"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Thiết bị có thể gập lại đang được mở ra"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Thiết bị có thể gập lại đang được lật ngược"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Còn <xliff:g id="PERCENTAGE">%s</xliff:g> pin"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Chuyển sang hồ sơ công việc"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Đóng"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Cài đặt màn hình khoá"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Không có Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Máy ảnh bị chặn"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Máy ảnh và micrô bị chặn"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrô bị chặn"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Chế độ ưu tiên đang bật"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/tiles_states_strings.xml b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
index 5b816fb9e62e..201a45b3d445 100644
--- a/packages/SystemUI/res/values-vi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Tắt"</item>
<item msgid="5966994759929723339">"Đang bật"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Không có sẵn"</item>
+ <item msgid="2478289035899842865">"Đang tắt"</item>
+ <item msgid="5137565285664080143">"Đang bật"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index f2ddb99a176a..0554b85a9bd9 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"如果您下次输入的 PIN 码仍然有误,您的工作资料及其相关数据将会被删除。"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"如果您下次输入的密码仍然有误,您的工作资料及其相关数据将会被删除。"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"请触摸指纹传感器"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"指纹图标"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"无法识别人脸。请改用指纹。"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"工作锁定屏幕"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"关闭"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"亮度"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"颜色反转"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色彩校正"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"字号"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"管理用户"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"完成"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"关闭"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"屏幕录制"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"无标题"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"待机"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"字体大小"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"缩小"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"放大"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大窗口"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大窗口控件"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"放大"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{已添加 # 个控件。}other{已添加 # 个控件。}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"添加“<xliff:g id="APPNAME">%s</xliff:g>”?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"当您添加“<xliff:g id="APPNAME">%s</xliff:g>”后,它可以将控件和内容添加到此面板。在某些应用中,您可以选择在此处显示哪些控件。"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"移除<xliff:g id="APPNAME">%s</xliff:g>的控件?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"已收藏"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"已收藏,位置:<xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"已取消收藏"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"其他"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"添加到设备控制器"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"添加"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"移除"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"来自<xliff:g id="APP">%s</xliff:g>的建议"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"设备已锁定"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"要从锁定屏幕上显示和控制设备吗?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"您可以在锁定屏幕上添加用于控制外部设备的控件。\n\n您的设备应用可能会允许您在不解锁手机或平板电脑的情况下控制某些设备。\n\n您可以随时在“设置”中进行更改。"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"要从锁定屏幕上控制设备吗?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"您可以在不解锁手机或平板电脑的情况下控制某些设备。\n\n您的设备应用将决定哪些设备可以通过这种方式进行控制。"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"不用了"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"是"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN 码由字母或符号组成"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"添加控制器"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"修改控制器"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"添加应用"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"移除应用"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"添加输出设备"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"群组"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"已选择 1 个设备"</string>
@@ -909,10 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"无法广播"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"无法保存,请重试。"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"无法保存。"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"必须至少 4 个字符"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"必须少于 16 个字符"</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>
@@ -963,7 +962,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"移动数据网络"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"已连接"</string>
- <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"暂时已连接"</string>
+ <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暂时连接"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"连接状况不佳"</string>
<string name="mobile_data_off_summary" msgid="3663995422004150567">"系统将不会自动连接到移动数据网络"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"无网络连接"</string>
@@ -1032,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• 至少有一台设备可用"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"轻触并按住快捷方式"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"取消"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"立即切换屏幕"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"展开手机"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"切换屏幕?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"若要获得更高的分辨率,请使用后置摄像头"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"若要获得更高的分辨率,请翻转手机"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展开可折叠设备"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻转可折叠设备"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"电池还剩 <xliff:g id="PERCENTAGE">%s</xliff:g> 的电量"</string>
@@ -1053,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"切换到工作资料"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"关闭"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"锁屏设置"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"没有 WLAN 连接"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"已禁用摄像头"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"已禁用摄像头和麦克风"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"已禁用麦克风"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"已开启优先模式"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
index 5d7d02f2dbeb..3ab2d7a3d1c7 100644
--- a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"关闭"</item>
<item msgid="5966994759929723339">"已开启"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"不可用"</item>
+ <item msgid="2478289035899842865">"已关闭"</item>
+ <item msgid="5137565285664080143">"已开启"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 1898f8c479b7..97d8411d989f 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"如果您下次輸入錯誤的 PIN,系統將會刪除工作設定檔和相關資料。"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"如果您下次輸入錯誤的密碼,系統將會刪除工作設定檔和相關資料。"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"請輕觸指紋感應器"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"指紋圖示"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"無法辨識面孔,請改用指紋完成驗證。"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -187,8 +186,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"電池電量為百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"目前電池電量為 <xliff:g id="PERCENTAGE">%1$d</xliff:g>,剩餘使用時間為 <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"正在充電:<xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%。"</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"目前電池電量為 <xliff:g id="PERCENTAGE">%d</xliff:g>。為保護電池,系統已暫停充電。"</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"目前電池電量為 <xliff:g id="PERCENTAGE">%1$d</xliff:g>,剩餘使用時間為 <xliff:g id="TIME">%2$s</xliff:g>。為保護電池,系統已暫停充電。"</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"目前電池電量為百分之 <xliff:g id="PERCENTAGE">%d</xliff:g>。為保護電池,系統已暫停充電。"</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"目前電池電量為百分之 <xliff:g id="PERCENTAGE">%1$d</xliff:g>,剩餘使用時間為 <xliff:g id="TIME">%2$s</xliff:g>。為保護電池,系統已暫停充電。"</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"睇所有通知"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter (TTY) 已啟用。"</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"鈴聲震動。"</string>
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"工作螢幕鎖定"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"亮度"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"色彩反轉"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色彩校正"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"字型大小"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"管理使用者"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"完成"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"關閉"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"錄製螢幕畫面"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"待機"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"字型大小"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"縮小"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"放大"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大視窗"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大視窗控制項"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"放大"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{已新增 # 個控制項。}other{已新增 # 個控制項。}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"要新增「<xliff:g id="APPNAME">%s</xliff:g>」嗎?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"如果您新增「<xliff:g id="APPNAME">%s</xliff:g>」,應用程式可將控制項和內容新增至此面板。部份應用程式可讓您選擇要在這裡顯示的控制項。"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"要移除「<xliff:g id="APPNAME">%s</xliff:g>」的控制項嗎?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"已加入收藏"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"已加入至收藏位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"已取消收藏"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"其他"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"加到裝置控制"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"新增"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"移除"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"由「<xliff:g id="APP">%s</xliff:g>」提供的建議"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"裝置已上鎖"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"要從上鎖畫面查看及控制裝置嗎?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"您可以在上鎖畫面新增外部裝置的控制項。\n\n裝置應用程式可能會讓您在不解鎖手機或平板電腦的情況下控制部分裝置。\n\n您可隨時在「設定」中作出變更。"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"要在上鎖畫面控制裝置嗎?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"您可以在不解鎖手機或平板電腦的情況下控制部分裝置。\n\n裝置應用程式決定哪些裝置可透過此方式控制。"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"不用了,謝謝"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"是"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN 含有字母或符號"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"新增控制項"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"編輯控制項"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"新增應用程式"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"移除應用程式"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"新增輸出裝置"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"群組"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"已選取 1 部裝置"</string>
@@ -909,8 +910,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"無法廣播"</string>
<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>
- <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"不得超過 16 個半形字元"</string>
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"請至少使用 4 個字元"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"請使用少於 16 個字元"</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>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• 至少一部裝置可用"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"輕觸並按住快速鍵"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"取消"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"立即切換螢幕"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"打開手機"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"要切換螢幕嗎?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"如要提高解像度,請使用後置鏡頭"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"如要提高解像度,請切換至手機後置鏡頭"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展開折疊式裝置"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻轉折疊式裝置"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"剩餘電量:<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"切換至工作設定檔"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"關閉"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"上鎖畫面設定"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"無法連線至 Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"已封鎖相機"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"已封鎖相機和麥克風"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"已封鎖麥克風"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"優先模式已開啟"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
index 2e51f920055a..89d66284ede6 100644
--- a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"已關閉"</item>
<item msgid="5966994759929723339">"已開啟"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"無法使用"</item>
+ <item msgid="2478289035899842865">"關閉"</item>
+ <item msgid="5137565285664080143">"開啟"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index a1296507fc61..d1512301b1e2 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"如果下次輸入的 PIN 碼仍不正確,系統將刪除你的工作資料夾和相關資料。"</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"如果下次輸入的密碼仍不正確,系統將刪除你的工作資料夾和相關資料。"</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"請輕觸指紋感應器"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"指紋圖示"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"無法辨識臉孔,請改用指紋完成驗證。"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<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_work_lock" msgid="4355620395354680575">"Work 螢幕鎖定"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"亮度"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"色彩反轉"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色彩校正"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"字型大小"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"管理使用者"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"完成"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"關閉"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"錄製螢幕畫面"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"待機"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"字型大小"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"縮小"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"放大"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大視窗"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大視窗控制項"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"放大"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{已新增 # 個控制項。}other{已新增 # 個控制項。}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"要新增「<xliff:g id="APPNAME">%s</xliff:g>」嗎?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"當你新增「<xliff:g id="APPNAME">%s</xliff:g>」時,應用程式也可將控制選項及內容新增到這個面板。某些應用程式可讓你選擇要顯示在這裡的控制選項。"</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"要移除「<xliff:g id="APPNAME">%s</xliff:g>」的控制嗎?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"已加入收藏"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"已加入收藏,位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"從收藏中移除"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"其他"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"新增至裝置控制項"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"新增"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"移除"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"來自「<xliff:g id="APP">%s</xliff:g>」的建議"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"裝置已鎖定"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"要在螢幕鎖定畫面上查看及控制裝置嗎?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"你可以在螢幕鎖定畫面上新增外部裝置的控制選項。\n\n你或許可透過裝置應用程式控制某些裝置,而不必解鎖手機或平板電腦。\n\n你隨時可以前往「設定」進行變更。"</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"要在螢幕鎖定畫面上控制裝置嗎?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"你可以直接控制某些裝置,不必解鎖手機或平板電腦。\n\n裝置應用程式會判斷可透過這種方式控制的應用程式。"</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"不用了,謝謝"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"是"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN 碼含有字母或符號"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"新增控制項"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"編輯控制項"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"新增應用程式"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"移除應用程式"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"新增輸出裝置"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"群組"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"已選取 1 部裝置"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• 至少要有一部可用裝置"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"按住快速鍵"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"取消"</string>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"立即切換螢幕"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"展開手機"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"要切換螢幕嗎?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"如要提高解析度,請使用後置鏡頭"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"如要提高解析度,請切換至手機後置鏡頭"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展開的折疊式裝置"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻轉折疊式裝置"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"剩餘電量:<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"切換至工作資料夾"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"關閉"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"螢幕鎖定設定"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"無法連上 Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"已封鎖攝影機"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"已封鎖攝影機和麥克風"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"已封鎖麥克風"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"優先模式已開啟"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
index f1f01853d342..a046e3354729 100644
--- a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"已關閉"</item>
<item msgid="5966994759929723339">"已開啟"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"無法使用"</item>
+ <item msgid="2478289035899842865">"關閉"</item>
+ <item msgid="5137565285664080143">"開啟"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 16f184a9a823..aa09a0074e99 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -168,7 +168,6 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Uma ufaka iphinikhodi engalungile kumzamo olandelayo, iphrofayela yakho yomsebenzi nedatha yayo izosuswa."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Uma ufake iphasiwedi engalungile kumzamo olandelayo, iphrofayela yakho yomsebenzi nedatha yayo izosuswa."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Thinta inzwa yesigxivizo zeminwe"</string>
- <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Isithonjana sezigxivizo zeminwe"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ayibazi ubuso. Sebenzisa izigxivizo zeminwe kunalokho."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
@@ -197,6 +196,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Umthunzi wesaziso."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Izilingiselelo ezisheshayo."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Amasethingi asheshayo Nomthunzi wezaziso."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Khiya isikrini."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ukukhiya isikrini somsebenzi"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Vala"</string>
@@ -257,8 +257,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ukugqama"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ukuguqulwa kombala"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Ukulungiswa kombala"</string>
- <!-- no translation found for quick_settings_font_scaling_label (5289001009876936768) -->
- <skip />
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Usayizi wefonti"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Phatha abasebenzisi"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Kwenziwe"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Vala"</string>
@@ -779,12 +778,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ukurekhoda isikrini"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Asikho isihloko"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Ilindile"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Usayizi Wefonti"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Yenza kube kuncane"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Yenza kube kukhulu"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Iwindi Lesikhulisi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Izilawuli Zewindi Lesikhulisi"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Sondeza"</string>
@@ -811,7 +807,9 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{ulawulo olu-# olwengeziwe.}one{ukulawulwa okungu-# okwengeziwe.}other{ukulawulwa okungu-# okwengeziwe.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Isusiwe"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Engeza i-<xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="4540047176861801815">"Uma wengeza i-<xliff:g id="APPNAME">%s</xliff:g>, ingangeza izilawuli nokuqukethwe kuleli phaneli. Kwamanye ama-app, ungakhetha ukuthi yiziphi izilawuli eziboniswa lapha."</string>
+ <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+ <skip />
+ <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Susa izilawuli ze-<xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Kwenziwe intandokazi"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Kwenziwe intandokazi, isimo esiyi-<xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Akwenziwanga intandokazi"</string>
@@ -829,12 +827,14 @@
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Okunye"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Engeza kuzilawuli zezinsiza"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Engeza"</string>
+ <string name="controls_dialog_remove" msgid="3775288002711561936">"Susa"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Kuphakanyiswe ngu-<xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Idivayisi ikhiyiwe"</string>
<string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Bonisa futhi ulawule amadivayisi ekukhiyeni isikrini?"</string>
<string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Ungakwazi ukwengeza izilawuli zamadivayisi wakho angaphandle ekukhiyeni isikrini.\n\nI-app yakho yedivayisi ingakuvumela ukuthi ulawule amanye amadivayisi ngaphandle kokuvula ifoni noma ithebulethi yakho.\n\nUngenza izinguquko nganoma yisiphi isikhathi Kumasethingi."</string>
<string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Lawula amadivayisi ekukhiyeni isikrini?"</string>
- <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Ungalawula amanye amadivayisi ngaphandle kokuvula ifoni noma ithebulethi yakho.\n\nI-app yakho yedivayisi inquma ukuthi imaphi amadivayisi angalawulwa ngale ndlela."</string>
+ <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+ <skip />
<string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Cha ngiyabonga"</string>
<string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yebo"</string>
<string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Iphinikhodi iqukethe amaletha namasimbui"</string>
@@ -882,6 +882,7 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Engeza Izilawuli"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Hlela izilawuli"</string>
<string name="controls_menu_add_another_app" msgid="8661172304650786705">"Engeza i-app"</string>
+ <string name="controls_menu_remove" msgid="3006525275966023468">"Susa i-app"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Engeza okukhiphayo"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Iqembu"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"idivayisi ekhethiwe e-1"</string>
@@ -1030,16 +1031,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Okungenani idivayisi eyodwa iyatholakala"</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>
- <!-- no translation found for rear_display_bottom_sheet_confirm (1507591562761552899) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_title (3930008746560711990) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_title (6291111173057304055) -->
- <skip />
- <!-- no translation found for rear_display_folded_bottom_sheet_description (6842767125783222695) -->
- <skip />
- <!-- no translation found for rear_display_unfolded_bottom_sheet_description (7229961336309960201) -->
- <skip />
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Shintsha izikrini manje"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Vula ifoni"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Shintsha izikrini?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Ukuze uthole ukulungiswa okuphezulu, sebenzisa ikhamera yangemuva"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Ukuze uthole ukulungiswa okuphezulu, phendula ifoni"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Idivayisi egoqekayo iyembulwa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Idivayisi egoqekayo iphendulwa nxazonke"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ibhethri elisele"</string>
@@ -1051,4 +1047,9 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Shintshela kuphrofayela yomsebenzi"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Vala"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Amasethingi okukhiya isikrini"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"I-Wi-Fi ayitholakali"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Ikhamera ivinjiwe"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Ikhamera nemakrofoni zivinjiwe"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Imakrofoni ivinjiwe"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Imodi ebalulekile ivuliwe"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/tiles_states_strings.xml b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
index a8ccbb58366a..e35840b85ab4 100644
--- a/packages/SystemUI/res/values-zu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
@@ -176,7 +176,9 @@
<item msgid="8014986104355098744">"Valiwe"</item>
<item msgid="5966994759929723339">"Vuliwe"</item>
</string-array>
- <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) -->
- <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) -->
- <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) -->
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ayitholakali"</item>
+ <item msgid="2478289035899842865">"Valiwe"</item>
+ <item msgid="5137565285664080143">"Vuliwe"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index ca4217f64b60..3763b1747197 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -161,6 +161,7 @@
<color name="GM2_red_300">#F28B82</color>
<color name="GM2_red_500">#EA4335</color>
+ <color name="GM2_red_600">#B3261E</color>
<color name="GM2_red_700">#C5221F</color>
<color name="GM2_blue_300">#8AB4F8</color>
@@ -207,6 +208,11 @@
<color name="control_thumbnail_shadow_color">@*android:color/black</color>
<color name="controls_task_view_bg">#CC191C1D</color>
+ <!-- Keyboard backlight indicator-->
+ <color name="backlight_indicator_step_filled">#F6E388</color>
+ <color name="backlight_indicator_step_empty">#494740</color>
+ <color name="backlight_indicator_background">#32302A</color>
+
<!-- Docked misalignment message -->
<color name="misalignment_text_color">#F28B82</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 3f84ddb2a067..f545dae05b56 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -774,7 +774,7 @@
<!-- Duration in milliseconds of the dream in complications fade-in animation. -->
<integer name="config_dreamOverlayInComplicationsDurationMs">250</integer>
<!-- Duration in milliseconds of the y-translation animation when entering a dream -->
- <integer name="config_dreamOverlayInTranslationYDurationMs">917</integer>
+ <integer name="config_dreamOverlayInTranslationYDurationMs">1167</integer>
<!-- Delay in milliseconds before switching to the dock user and dreaming if a secondary user is
active when the device is locked and docked. 0 indicates disabled. Default is 1 minute. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d48ea214e8d9..262086f43d89 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -196,9 +196,6 @@
<!-- Increased height of a small notification in the status bar -->
<dimen name="notification_min_height_increased">146dp</dimen>
- <!-- Increased height of a collapsed media notification in the status bar -->
- <dimen name="notification_min_height_media">160dp</dimen>
-
<!-- Height of a small notification in the status bar which was used before android N -->
<dimen name="notification_min_height_legacy">64dp</dimen>
@@ -576,7 +573,7 @@
<dimen name="qs_tile_margin_horizontal">8dp</dimen>
<dimen name="qs_tile_margin_vertical">@dimen/qs_tile_margin_horizontal</dimen>
<dimen name="qs_tile_margin_top_bottom">4dp</dimen>
- <dimen name="qs_brightness_margin_top">12dp</dimen>
+ <dimen name="qs_brightness_margin_top">8dp</dimen>
<dimen name="qs_brightness_margin_bottom">16dp</dimen>
<dimen name="qqs_layout_margin_top">16dp</dimen>
<dimen name="qqs_layout_padding_bottom">24dp</dimen>
@@ -616,8 +613,7 @@
<dimen name="qs_dual_tile_padding_horizontal">6dp</dimen>
<dimen name="qs_panel_elevation">4dp</dimen>
<dimen name="qs_panel_padding_bottom">@dimen/footer_actions_height</dimen>
- <dimen name="qs_panel_padding_top">48dp</dimen>
- <dimen name="qs_panel_padding_top_combined_headers">80dp</dimen>
+ <dimen name="qs_panel_padding_top">80dp</dimen>
<dimen name="qs_data_usage_text_size">14sp</dimen>
<dimen name="qs_data_usage_usage_text_size">36sp</dimen>
@@ -629,7 +625,7 @@
<dimen name="qs_header_row_min_height">48dp</dimen>
<dimen name="qs_header_non_clickable_element_height">24dp</dimen>
- <dimen name="new_qs_header_non_clickable_element_height">20dp</dimen>
+ <dimen name="new_qs_header_non_clickable_element_height">24dp</dimen>
<dimen name="qs_footer_padding">20dp</dimen>
<dimen name="qs_security_footer_height">88dp</dimen>
@@ -1115,14 +1111,15 @@
<dimen name="qs_media_rec_album_title_bottom_margin">22dp</dimen>
<dimen name="qs_media_rec_album_subtitle_height">12dp</dimen>
- <!-- Media tap-to-transfer chip for sender device -->
- <dimen name="media_ttt_chip_outer_padding">16dp</dimen>
- <dimen name="media_ttt_text_size">16sp</dimen>
- <dimen name="media_ttt_app_icon_size">24dp</dimen>
- <dimen name="media_ttt_status_icon_size">20dp</dimen>
- <dimen name="media_ttt_undo_button_vertical_padding">8dp</dimen>
- <dimen name="media_ttt_undo_button_vertical_negative_margin">-8dp</dimen>
- <dimen name="media_ttt_last_item_start_margin">12dp</dimen>
+ <!-- Chipbar -->
+ <!-- (Used for media tap-to-transfer chip for sender device and active unlock) -->
+ <dimen name="chipbar_outer_padding">16dp</dimen>
+ <dimen name="chipbar_text_size">16sp</dimen>
+ <dimen name="chipbar_start_icon_size">24dp</dimen>
+ <dimen name="chipbar_end_icon_size">20dp</dimen>
+ <dimen name="chipbar_end_button_vertical_padding">8dp</dimen>
+ <dimen name="chipbar_end_button_vertical_negative_margin">-8dp</dimen>
+ <dimen name="chipbar_end_item_start_margin">12dp</dimen>
<!-- Media tap-to-transfer chip for receiver device -->
<dimen name="media_ttt_icon_size_receiver">112dp</dimen>
@@ -1154,11 +1151,13 @@
<!-- Home Controls -->
<dimen name="controls_header_menu_size">48dp</dimen>
+ <dimen name="controls_header_menu_button_size">48dp</dimen>
<dimen name="controls_header_bottom_margin">16dp</dimen>
+ <dimen name="controls_header_horizontal_padding">12dp</dimen>
<dimen name="controls_header_app_icon_size">24dp</dimen>
<dimen name="controls_top_margin">48dp</dimen>
- <dimen name="controls_padding_horizontal">0dp</dimen>
- <dimen name="control_header_text_size">20sp</dimen>
+ <dimen name="controls_content_margin_horizontal">0dp</dimen>
+ <dimen name="control_header_text_size">24sp</dimen>
<dimen name="control_item_text_size">16sp</dimen>
<dimen name="control_menu_item_text_size">16sp</dimen>
<dimen name="control_menu_item_min_height">56dp</dimen>
@@ -1189,6 +1188,8 @@
<item name="controls_task_view_width_percentage" translatable="false" format="float" type="dimen">1.0</item>
<dimen name="controls_task_view_right_margin">0dp</dimen>
+ <dimen name="controls_panel_corner_radius">42dp</dimen>
+
<!-- Home Controls activity view detail panel-->
<dimen name="controls_activity_view_corner_radius">@*android:dimen/config_bottomDialogCornerRadius</dimen>
@@ -1584,6 +1585,10 @@
<!-- Dream overlay complications related dimensions -->
<!-- The blur radius applied to the dream overlay when entering and exiting dreams -->
<dimen name="dream_overlay_anim_blur_radius">50dp</dimen>
+ <dimen name="dream_overlay_bottom_affordance_height">64dp</dimen>
+ <dimen name="dream_overlay_bottom_affordance_width">64dp</dimen>
+ <dimen name="dream_overlay_bottom_affordance_radius">32dp</dimen>
+ <dimen name="dream_overlay_bottom_affordance_padding">14dp</dimen>
<dimen name="dream_overlay_complication_clock_time_text_size">86dp</dimen>
<dimen name="dream_overlay_complication_clock_time_translation_y">28dp</dimen>
<dimen name="dream_overlay_complication_home_controls_padding">28dp</dimen>
@@ -1653,6 +1658,19 @@
<dimen name="media_output_broadcast_info_summary_height">20dp</dimen>
<dimen name="media_output_broadcast_info_edit">18dp</dimen>
+ <!-- Keyboard backlight indicator-->
+ <dimen name="backlight_indicator_root_corner_radius">48dp</dimen>
+ <dimen name="backlight_indicator_root_vertical_padding">8dp</dimen>
+ <dimen name="backlight_indicator_root_horizontal_padding">4dp</dimen>
+ <dimen name="backlight_indicator_icon_width">22dp</dimen>
+ <dimen name="backlight_indicator_icon_height">11dp</dimen>
+ <dimen name="backlight_indicator_icon_left_margin">2dp</dimen>
+ <dimen name="backlight_indicator_step_width">52dp</dimen>
+ <dimen name="backlight_indicator_step_height">40dp</dimen>
+ <dimen name="backlight_indicator_step_horizontal_margin">4dp</dimen>
+ <dimen name="backlight_indicator_step_small_radius">4dp</dimen>
+ <dimen name="backlight_indicator_step_large_radius">48dp</dimen>
+
<!-- Broadcast dialog -->
<dimen name="broadcast_dialog_title_img_margin_top">18dp</dimen>
<dimen name="broadcast_dialog_title_text_size">24sp</dimen>
@@ -1701,4 +1719,9 @@
it is long-pressed.
-->
<dimen name="keyguard_long_press_settings_popup_vertical_offset">96dp</dimen>
+
+
+ <!-- Bouncer user switcher margins -->
+ <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">0dp</dimen>
+ <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index 6354752e1b22..763930db1d55 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -30,9 +30,6 @@
<bool name="flag_charging_ripple">false</bool>
- <!-- Whether to show chipbar UI whenever the device is unlocked by ActiveUnlock. -->
- <bool name="flag_active_unlock_chipbar">true</bool>
-
<!-- Whether the user switcher chip shows in the status bar. When true, the multi user
avatar will no longer show on the lockscreen -->
<bool name="flag_user_switcher_chip">false</bool>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e6ac59e6b106..9a9f5106b7d8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -405,8 +405,6 @@
<!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication -->
<string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
- <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_fingerprint_dialog_fingerprint_icon">Fingerprint icon</string>
<!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
<string name="fingerprint_dialog_use_fingerprint_instead">Can\u2019t recognize face. Use fingerprint instead.</string>
<!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
@@ -479,6 +477,8 @@
<string name="accessibility_desc_notification_shade">Notification shade.</string>
<!-- Content description for the quick settings panel (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_quick_settings">Quick settings.</string>
+ <!-- Content description for the split notification shade that also includes QS (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_desc_qs_notification_shade">Quick settings and Notification shade.</string>
<!-- Content description for the lock screen (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_lock_screen">Lock screen.</string>
<!-- Content description for the work profile lock screen. This prevents work profile apps from being used, but personal apps can be used as normal (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -2258,7 +2258,11 @@
<!-- Shows in a dialog presented to the user to authorize this app to display a Device controls
panel (embedded activity) instead of controls rendered by SystemUI [CHAR LIMIT=NONE] -->
- <string name="controls_panel_authorization">When you add <xliff:g id="appName" example="My app">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here.</string>
+ <string name="controls_panel_authorization"><xliff:g id="appName" example="My app">%s</xliff:g>can choose which controls and content show here.</string>
+
+ <!-- Shows in a dialog presented to the user to authorize this app removal from a Device
+ controls panel [CHAR LIMIT=NONE] -->
+ <string name="controls_panel_remove_app_authorization">Remove controls for <xliff:g example="My app" id="appName">%s</xliff:g>?</string>
<!-- a11y state description for a control that is currently favorited [CHAR LIMIT=NONE] -->
<string name="accessibility_control_favorite">Favorited</string>
@@ -2300,6 +2304,8 @@
<string name="controls_dialog_title">Add to device controls</string>
<!-- Controls dialog add to favorites [CHAR LIMIT=40] -->
<string name="controls_dialog_ok">Add</string>
+ <!-- Controls dialog remove app from a panel [CHAR LIMIT=40] -->
+ <string name="controls_dialog_remove">Remove</string>
<!-- Controls dialog message. Indicates app that suggested this control [CHAR LIMIT=NONE] -->
<string name="controls_dialog_message">Suggested by <xliff:g id="app" example="System UI">%s</xliff:g></string>
<!-- Controls tile secondary label when device is locked and user does not want access to controls from lockscreen [CHAR LIMIT=20] -->
@@ -2312,7 +2318,7 @@
<!-- Title of the dialog to control certain devices from lock screen without auth [CHAR LIMIT=NONE] -->
<string name="controls_settings_trivial_controls_dialog_title">Control devices from lock screen?</string>
<!-- Message of the dialog to control certain devices from lock screen without auth [CHAR LIMIT=NONE] -->
- <string name="controls_settings_trivial_controls_dialog_message">You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way.</string>
+ <string name="controls_settings_trivial_controls_dialog_message">You can control some devices without unlocking your phone or tablet. Your device app determines which devices can be controlled in this way.</string>
<!-- Neutral button title of the controls dialog [CHAR LIMIT=NONE] -->
<string name="controls_settings_dialog_neutral_button">No thanks</string>
<!-- Positive button title of the controls dialog [CHAR LIMIT=NONE] -->
@@ -2417,6 +2423,8 @@
<string name="controls_menu_edit">Edit controls</string>
<!-- Controls menu, add another app [CHAR LIMIT=30] -->
<string name="controls_menu_add_another_app">Add app</string>
+ <!-- Controls menu, remove app [CHAR_LIMIT=30] -->
+ <string name="controls_menu_remove">Remove app</string>
<!-- Title for the media output dialog with media related devices [CHAR LIMIT=50] -->
<string name="media_output_dialog_add_output">Add outputs</string>
diff --git a/packages/SystemUI/screenshot/AndroidManifest.xml b/packages/SystemUI/screenshot/AndroidManifest.xml
index a405836bd77f..ba3dc8c53fff 100644
--- a/packages/SystemUI/screenshot/AndroidManifest.xml
+++ b/packages/SystemUI/screenshot/AndroidManifest.xml
@@ -20,6 +20,7 @@
<application>
<activity
android:name="com.android.systemui.testing.screenshot.ScreenshotActivity"
+ android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
android:exported="true"
android:theme="@style/Theme.SystemUI.Screenshot" />
</application>
diff --git a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
index 738b37c9eea4..2d47356f2ce1 100644
--- a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
+++ b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
@@ -39,14 +39,14 @@ import platform.test.screenshot.getEmulatedDevicePathConfig
import platform.test.screenshot.matchers.BitmapMatcher
/** A rule for View screenshot diff unit tests. */
-class ViewScreenshotTestRule(
+open class ViewScreenshotTestRule(
emulationSpec: DeviceEmulationSpec,
private val matcher: BitmapMatcher = UnitTestBitmapMatcher,
assetsPathRelativeToBuildRoot: String
) : TestRule {
private val colorsRule = MaterialYouColorsRule()
private val deviceEmulationRule = DeviceEmulationRule(emulationSpec)
- private val screenshotRule =
+ protected val screenshotRule =
ScreenshotTestRule(
SystemUIGoldenImagePathManager(
getEmulatedDevicePathConfig(emulationSpec),
@@ -64,15 +64,10 @@ class ViewScreenshotTestRule(
return delegateRule.apply(base, description)
}
- /**
- * Compare the content of the view provided by [viewProvider] with the golden image identified
- * by [goldenIdentifier] in the context of [emulationSpec].
- */
- fun screenshotTest(
- goldenIdentifier: String,
+ protected fun takeScreenshot(
mode: Mode = Mode.WrapContent,
viewProvider: (ComponentActivity) -> View,
- ) {
+ ): Bitmap {
activityRule.scenario.onActivity { activity ->
// Make sure that the activity draws full screen and fits the whole display instead of
// the system bars.
@@ -99,7 +94,19 @@ class ViewScreenshotTestRule(
contentView = content.getChildAt(0)
}
- val bitmap = contentView?.toBitmap() ?: error("contentView is null")
+ return contentView?.toBitmap() ?: error("contentView is null")
+ }
+
+ /**
+ * Compare the content of the view provided by [viewProvider] with the golden image identified
+ * by [goldenIdentifier] in the context of [emulationSpec].
+ */
+ fun screenshotTest(
+ goldenIdentifier: String,
+ mode: Mode = Mode.WrapContent,
+ viewProvider: (ComponentActivity) -> View,
+ ) {
+ val bitmap = takeScreenshot(mode, viewProvider)
screenshotRule.assertBitmapAgainstGolden(
bitmap,
goldenIdentifier,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
index c9a25b067b94..b6aae69ebad6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
@@ -145,7 +145,7 @@ data class SysPropBooleanFlag constructor(
override val namespace: String,
override val default: Boolean = false,
) : SysPropFlag<Boolean> {
- // TODO(b/223379190): Teamfood not supported for sysprop flags yet.
+ // TODO(b/268520433): Teamfood not supported for sysprop flags yet.
override val teamfood: Boolean = false
}
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 12e0b9ab835a..c5979cc50c3c 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,35 +65,40 @@ class UnfoldConstantTranslateAnimator(
} else {
1
}
- viewsToTranslate.forEach { (view, direction, shouldBeAnimated) ->
- if (shouldBeAnimated()) {
- view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier
- }
+ viewsToTranslate.forEach { (view, direction) ->
+ view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier
}
}
/** Finds in [parent] all views specified by [ids] and register them for the animation. */
private fun registerViewsForAnimation(parent: ViewGroup, ids: Set<ViewIdToTranslate>) {
viewsToTranslate =
- ids.mapNotNull { (id, dir, pred) ->
- parent.findViewById<View>(id)?.let { view ->
- ViewToTranslate(WeakReference(view), dir, pred)
+ ids.asSequence()
+ .filter { it.shouldBeAnimated() }
+ .mapNotNull {
+ parent.findViewById<View>(it.viewId)?.let { view ->
+ ViewToTranslate(WeakReference(view), it.direction)
+ }
}
- }
+ .toList()
}
- /** Represents a view to animate. [rootView] should contain a view with [viewId] inside. */
+ /**
+ * Represents a view to animate. [rootView] should contain a view with [viewId] inside.
+ * [shouldBeAnimated] is only evaluated when the viewsToTranslate is registered in
+ * [registerViewsForAnimation].
+ */
data class ViewIdToTranslate(
val viewId: Int,
val direction: Direction,
val shouldBeAnimated: () -> Boolean = { true }
)
- private data class ViewToTranslate(
- val view: WeakReference<View>,
- val direction: Direction,
- val shouldBeAnimated: () -> Boolean
- )
+ /**
+ * 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)
/** Direction of the animation. */
enum class Direction(val multiplier: Float) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
index 23742c503ed3..454294f36d2a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
@@ -87,7 +87,7 @@ internal object Evaluator {
* Helper for evaluating 3-valued logical AND/OR.
*
* @param returnValueIfAnyMatches AND returns false if any value is false. OR returns true if
- * any value is true.
+ * any value is true.
*/
private fun threeValuedAndOrOr(
conditions: Collection<Condition>,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
index b92715516a75..0c2341f9480c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
@@ -33,8 +33,6 @@ public class PreviewPositionHelper {
*/
public static final int STAGE_POSITION_BOTTOM_OR_RIGHT = 1;
- // Contains the portion of the thumbnail that is unclipped when fullscreen progress = 1.
- private final RectF mClippedInsets = new RectF();
private final Matrix mMatrix = new Matrix();
private boolean mIsOrientationChanged;
private SplitBounds mSplitBounds;
@@ -62,7 +60,7 @@ public class PreviewPositionHelper {
*/
public void updateThumbnailMatrix(Rect thumbnailBounds, ThumbnailData thumbnailData,
int canvasWidth, int canvasHeight, int screenWidthPx, int screenHeightPx,
- int taskbarSize, boolean isTablet,
+ int taskbarSize, boolean isLargeScreen,
int currentRotation, boolean isRtl) {
boolean isRotated = false;
boolean isOrientationDifferent;
@@ -70,40 +68,13 @@ public class PreviewPositionHelper {
int thumbnailRotation = thumbnailData.rotation;
int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation);
RectF thumbnailClipHint = new RectF();
-
- float scaledTaskbarSize;
- float canvasScreenRatio;
- if (mSplitBounds != null) {
- if (mSplitBounds.appsStackedVertically) {
- if (mDesiredStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
- // Top app isn't cropped at all by taskbar
- canvasScreenRatio = 0;
- } else {
- // Same as fullscreen ratio
- canvasScreenRatio = (float) canvasWidth / screenWidthPx;
- }
- } else {
- // For landscape, scale the width
- float taskPercent = mDesiredStagePosition == STAGE_POSITION_TOP_OR_LEFT
- ? mSplitBounds.leftTaskPercent
- : (1 - (mSplitBounds.leftTaskPercent + mSplitBounds.dividerWidthPercent));
- // Scale landscape width to that of actual screen
- float fullscreenTaskWidth = screenWidthPx * taskPercent;
- canvasScreenRatio = canvasWidth / fullscreenTaskWidth;
- }
- } else {
- canvasScreenRatio = (float) canvasWidth / screenWidthPx;
- }
- scaledTaskbarSize = taskbarSize * canvasScreenRatio;
- thumbnailClipHint.bottom = isTablet ? scaledTaskbarSize : 0;
-
float scale = thumbnailData.scale;
final float thumbnailScale;
// Landscape vs portrait change.
// Note: Disable rotation in grid layout.
boolean windowingModeSupportsRotation =
- thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN && !isTablet;
+ thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN && !isLargeScreen;
isOrientationDifferent = isOrientationChange(deltaRotate)
&& windowingModeSupportsRotation;
if (canvasWidth == 0 || canvasHeight == 0 || scale == 0) {
@@ -116,10 +87,8 @@ public class PreviewPositionHelper {
float surfaceWidth = thumbnailBounds.width() / scale;
float surfaceHeight = thumbnailBounds.height() / scale;
- float availableWidth = surfaceWidth
- - (thumbnailClipHint.left + thumbnailClipHint.right);
- float availableHeight = surfaceHeight
- - (thumbnailClipHint.top + thumbnailClipHint.bottom);
+ float availableWidth = surfaceWidth;
+ float availableHeight = surfaceHeight;
float canvasAspect = canvasWidth / (float) canvasHeight;
float availableAspect = isRotated
@@ -210,8 +179,6 @@ public class PreviewPositionHelper {
setThumbnailRotation(deltaRotate, thumbnailBounds);
}
- mClippedInsets.set(0, 0, 0, scaledTaskbarSize);
-
mMatrix.postScale(thumbnailScale, thumbnailScale);
mIsOrientationChanged = isOrientationDifferent;
}
@@ -250,8 +217,4 @@ public class PreviewPositionHelper {
}
mMatrix.postTranslate(translateX, translateY);
}
-
- public RectF getClippedInsets() {
- return mClippedInsets;
- }
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
index 77a13bd91b90..751a3f8458bd 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
@@ -137,7 +137,7 @@ public class Utilities {
/** @return whether or not {@param context} represents that of a large screen device or not */
@TargetApi(Build.VERSION_CODES.R)
- public static boolean isTablet(Context context) {
+ public static boolean isLargeScreen(Context context) {
final WindowManager windowManager = context.getSystemService(WindowManager.class);
final Rect bounds = windowManager.getCurrentWindowMetrics().getBounds();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
index 9a581aaa9b2c..482158e80d0f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
@@ -91,6 +91,22 @@ constructor(
val sampledRegion = calculateSampledRegion(sampledView)
val regions = ArrayList<RectF>()
val sampledRegionWithOffset = convertBounds(sampledRegion)
+
+ if (
+ sampledRegionWithOffset.left < 0.0 ||
+ sampledRegionWithOffset.right > 1.0 ||
+ sampledRegionWithOffset.top < 0.0 ||
+ sampledRegionWithOffset.bottom > 1.0
+ ) {
+ android.util.Log.e(
+ "RegionSampler",
+ "view out of bounds: $sampledRegion | " +
+ "screen width: ${displaySize.x}, screen height: ${displaySize.y}",
+ Exception()
+ )
+ return
+ }
+
regions.add(sampledRegionWithOffset)
wallpaperManager?.removeOnColorsChangedListener(this)
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
index 359da13a9799..53fab69bd3b8 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
@@ -29,8 +29,11 @@ import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.SuppressLint;
import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
@@ -86,15 +89,16 @@ public class RotationButtonController {
private RotationButton mRotationButton;
private boolean mIsRecentsAnimationRunning;
+ private boolean mDocked;
private boolean mHomeRotationEnabled;
private int mLastRotationSuggestion;
private boolean mPendingRotationSuggestion;
private boolean mHoveringRotationSuggestion;
private final AccessibilityManager mAccessibilityManager;
private final TaskStackListenerImpl mTaskStackListener;
- private Consumer<Integer> mRotWatcherListener;
private boolean mListenersRegistered = false;
+ private boolean mRotationWatcherRegistered = false;
private boolean mIsNavigationBarShowing;
@SuppressLint("InlinedApi")
private @WindowInsetsController.Behavior
@@ -123,6 +127,12 @@ public class RotationButtonController {
() -> mPendingRotationSuggestion = false;
private Animator mRotateHideAnimator;
+ private final BroadcastReceiver mDockedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ updateDockedState(intent);
+ }
+ };
private final IRotationWatcher.Stub mRotationWatcher = new IRotationWatcher.Stub() {
@Override
@@ -130,21 +140,7 @@ public class RotationButtonController {
// We need this to be scheduled as early as possible to beat the redrawing of
// window in response to the orientation change.
mMainThreadHandler.postAtFrontOfQueue(() -> {
- // If the screen rotation changes while locked, potentially update lock to flow with
- // new screen rotation and hide any showing suggestions.
- boolean rotationLocked = isRotationLocked();
- // The isVisible check makes the rotation button disappear when we are not locked
- // (e.g. for tabletop auto-rotate).
- if (rotationLocked || mRotationButton.isVisible()) {
- if (shouldOverrideUserLockPrefs(rotation) && rotationLocked) {
- setRotationLockedAtAngle(rotation);
- }
- setRotateSuggestionButtonState(false /* visible */, true /* forced */);
- }
-
- if (mRotWatcherListener != null) {
- mRotWatcherListener.accept(rotation);
- }
+ onRotationWatcherChanged(rotation);
});
}
};
@@ -195,8 +191,11 @@ public class RotationButtonController {
return mContext;
}
+ /**
+ * Called during Taskbar initialization.
+ */
public void init() {
- registerListeners();
+ registerListeners(true /* registerRotationWatcher */);
if (mContext.getDisplay().getDisplayId() != DEFAULT_DISPLAY) {
// Currently there is no accelerometer sensor on non-default display, disable fixed
// rotation for non-default display
@@ -204,25 +203,35 @@ public class RotationButtonController {
}
}
+ /**
+ * Called during Taskbar uninitialization.
+ */
public void onDestroy() {
unregisterListeners();
}
- public void registerListeners() {
+ public void registerListeners(boolean registerRotationWatcher) {
if (mListenersRegistered || getContext().getPackageManager().hasSystemFeature(FEATURE_PC)) {
return;
}
mListenersRegistered = true;
- try {
- WindowManagerGlobal.getWindowManagerService()
- .watchRotation(mRotationWatcher, DEFAULT_DISPLAY);
- } catch (IllegalArgumentException e) {
- mListenersRegistered = false;
- Log.w(TAG, "RegisterListeners for the display failed");
- } catch (RemoteException e) {
- Log.e(TAG, "RegisterListeners caught a RemoteException", e);
- return;
+
+ updateDockedState(mContext.registerReceiver(mDockedReceiver,
+ new IntentFilter(Intent.ACTION_DOCK_EVENT)));
+
+ if (registerRotationWatcher) {
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .watchRotation(mRotationWatcher, DEFAULT_DISPLAY);
+ mRotationWatcherRegistered = true;
+ } catch (IllegalArgumentException e) {
+ mListenersRegistered = false;
+ Log.w(TAG, "RegisterListeners for the display failed", e);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RegisterListeners caught a RemoteException", e);
+ return;
+ }
}
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
@@ -234,20 +243,21 @@ public class RotationButtonController {
}
mListenersRegistered = false;
- try {
- WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(mRotationWatcher);
- } catch (RemoteException e) {
- Log.e(TAG, "UnregisterListeners caught a RemoteException", e);
- return;
+
+ mContext.unregisterReceiver(mDockedReceiver);
+ if (mRotationWatcherRegistered) {
+ try {
+ WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(
+ mRotationWatcher);
+ } catch (RemoteException e) {
+ Log.e(TAG, "UnregisterListeners caught a RemoteException", e);
+ return;
+ }
}
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
}
- public void setRotationCallback(Consumer<Integer> watcher) {
- mRotWatcherListener = watcher;
- }
-
public void setRotationLockedAtAngle(int rotationSuggestion) {
RotationPolicy.setRotationLockAtAngle(mContext, /* enabled= */ isRotationLocked(),
/* rotation= */ rotationSuggestion);
@@ -345,6 +355,15 @@ public class RotationButtonController {
updateRotationButtonStateInOverview();
}
+ private void updateDockedState(Intent intent) {
+ if (intent == null) {
+ return;
+ }
+
+ mDocked = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED)
+ != Intent.EXTRA_DOCK_STATE_UNDOCKED;
+ }
+
private void updateRotationButtonStateInOverview() {
if (mIsRecentsAnimationRunning && !mHomeRotationEnabled) {
setRotateSuggestionButtonState(false, true /* hideImmediately */);
@@ -401,6 +420,30 @@ public class RotationButtonController {
}
}
+ /**
+ * Called when the rotation watcher rotation changes, either from the watcher registered
+ * internally in this class, or a signal propagated from NavBarHelper.
+ */
+ public void onRotationWatcherChanged(int rotation) {
+ if (!mListenersRegistered) {
+ // Ignore if not registered
+ return;
+ }
+
+ // If the screen rotation changes while locked, potentially update lock to flow with
+ // new screen rotation and hide any showing suggestions.
+ boolean rotationLocked = isRotationLocked();
+ // The isVisible check makes the rotation button disappear when we are not locked
+ // (e.g. for tabletop auto-rotate).
+ if (rotationLocked || mRotationButton.isVisible()) {
+ // Do not allow a change in rotation to set user rotation when docked.
+ if (shouldOverrideUserLockPrefs(rotation) && rotationLocked && !mDocked) {
+ setRotationLockedAtAngle(rotation);
+ }
+ setRotateSuggestionButtonState(false /* visible */, true /* forced */);
+ }
+ }
+
public void onDisable2FlagChanged(int state2) {
final boolean rotateSuggestionsDisabled = hasDisable2RotateSuggestionFlag(state2);
if (rotateSuggestionsDisabled) onRotationSuggestionsDisabled();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 6bfaf5e49820..b2add4f661cb 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -18,7 +18,6 @@ package com.android.systemui.shared.system;
import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.app.ActivityTaskManager.getService;
import android.annotation.NonNull;
@@ -45,6 +44,7 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
+import android.view.Display;
import android.view.IRecentsAnimationController;
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationTarget;
@@ -112,6 +112,13 @@ public class ActivityManagerWrapper {
}
/**
+ * @see #getRunningTasks(boolean , int)
+ */
+ public ActivityManager.RunningTaskInfo[] getRunningTasks(boolean filterOnlyVisibleRecents) {
+ return getRunningTasks(filterOnlyVisibleRecents, Display.INVALID_DISPLAY);
+ }
+
+ /**
* We ask for {@link #NUM_RECENT_ACTIVITIES_REQUEST} activities because when in split screen,
* we'll get back 2 activities for each split app and one for launcher. Launcher might be more
* "recently" used than one of the split apps so if we only request 2 tasks, then we might miss
@@ -120,10 +127,12 @@ public class ActivityManagerWrapper {
* @return an array of up to {@link #NUM_RECENT_ACTIVITIES_REQUEST} running tasks
* filtering only for tasks that can be visible in the recent tasks list.
*/
- public ActivityManager.RunningTaskInfo[] getRunningTasks(boolean filterOnlyVisibleRecents) {
+ public ActivityManager.RunningTaskInfo[] getRunningTasks(boolean filterOnlyVisibleRecents,
+ int displayId) {
// Note: The set of running tasks from the system is ordered by recency
List<ActivityManager.RunningTaskInfo> tasks =
- mAtm.getTasks(NUM_RECENT_ACTIVITIES_REQUEST, filterOnlyVisibleRecents);
+ mAtm.getTasks(NUM_RECENT_ACTIVITIES_REQUEST,
+ filterOnlyVisibleRecents, /* keepInExtras= */ false, displayId);
return tasks.toArray(new RunningTaskInfo[tasks.size()]);
}
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
index 8323d0971ad7..f005bab55de6 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
@@ -23,6 +23,8 @@ import com.android.systemui.util.settings.SettingsUtilModule
import dagger.Binds
import dagger.Module
import dagger.Provides
+import dagger.multibindings.IntoSet
+import javax.inject.Named
@Module(includes = [
FeatureFlagsDebugStartableModule::class,
@@ -35,7 +37,8 @@ abstract class FlagsModule {
abstract fun bindsFeatureFlagDebug(impl: FeatureFlagsDebug): FeatureFlags
@Binds
- abstract fun bindsRestarter(debugRestarter: FeatureFlagsDebugRestarter): Restarter
+ @IntoSet
+ abstract fun bindsScreenIdleCondition(impl: ScreenIdleCondition): ConditionalRestarter.Condition
@Module
companion object {
@@ -44,5 +47,10 @@ abstract class FlagsModule {
fun provideFlagManager(context: Context, @Main handler: Handler): FlagManager {
return FlagManager(context, handler)
}
+
+ @JvmStatic
+ @Provides
+ @Named(ConditionalRestarter.RESTART_DELAY)
+ fun provideRestartDelaySec(): Long = 1
}
}
diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
index 87beff76290d..927d4604b823 100644
--- a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
@@ -18,6 +18,9 @@ package com.android.systemui.flags
import dagger.Binds
import dagger.Module
+import dagger.Provides
+import dagger.multibindings.IntoSet
+import javax.inject.Named
@Module(includes = [
FeatureFlagsReleaseStartableModule::class,
@@ -29,5 +32,18 @@ abstract class FlagsModule {
abstract fun bindsFeatureFlagRelease(impl: FeatureFlagsRelease): FeatureFlags
@Binds
- abstract fun bindsRestarter(debugRestarter: FeatureFlagsReleaseRestarter): Restarter
+ @IntoSet
+ abstract fun bindsScreenIdleCondition(impl: ScreenIdleCondition): ConditionalRestarter.Condition
+
+ @Binds
+ @IntoSet
+ abstract fun bindsPluggedInCondition(impl: PluggedInCondition): ConditionalRestarter.Condition
+
+ @Module
+ companion object {
+ @JvmStatic
+ @Provides
+ @Named(ConditionalRestarter.RESTART_DELAY)
+ fun provideRestartDelaySec(): Long = 30
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 1254e1ee3311..4aaa566eb852 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -21,6 +21,7 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Resources
+import android.graphics.Rect
import android.text.format.DateFormat
import android.util.TypedValue
import android.view.View
@@ -48,7 +49,7 @@ import com.android.systemui.plugins.ClockTickRate
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel.DEBUG
import com.android.systemui.shared.regionsampling.RegionSampler
-import com.android.systemui.plugins.Weather
+import com.android.systemui.plugins.WeatherData
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -119,10 +120,6 @@ constructor(
private val mLayoutChangedListener =
object : View.OnLayoutChangeListener {
- private var currentSmallClockView: View? = null
- private var currentLargeClockView: View? = null
- private var currentSmallClockLocation = IntArray(2)
- private var currentLargeClockLocation = IntArray(2)
override fun onLayoutChange(
view: View?,
@@ -135,6 +132,8 @@ constructor(
oldRight: Int,
oldBottom: Int
) {
+ view?.removeOnLayoutChangeListener(this)
+
val parent = (view?.parent) as FrameLayout
// don't pass in negative bounds when clocks are in transition state
@@ -142,31 +141,12 @@ constructor(
return
}
- // SMALL CLOCK
- if (parent.id == R.id.lockscreen_clock_view) {
- // view bounds have changed due to clock size changing (i.e. different character
- // widths)
- // AND/OR the view has been translated when transitioning between small and
- // large clock
- if (
- view != currentSmallClockView ||
- !view.locationOnScreen.contentEquals(currentSmallClockLocation)
- ) {
- currentSmallClockView = view
- currentSmallClockLocation = view.locationOnScreen
- updateRegionSampler(view)
- }
- }
- // LARGE CLOCK
- else if (parent.id == R.id.lockscreen_clock_view_large) {
- if (
- view != currentLargeClockView ||
- !view.locationOnScreen.contentEquals(currentLargeClockLocation)
- ) {
- currentLargeClockView = view
- currentLargeClockLocation = view.locationOnScreen
- updateRegionSampler(view)
- }
+ val currentViewRect = Rect(left, top, right, bottom)
+ val oldViewRect = Rect(oldLeft, oldTop, oldRight, oldBottom)
+
+ if (currentViewRect.width() != oldViewRect.width() ||
+ currentViewRect.height() != oldViewRect.height()) {
+ updateRegionSampler(view)
}
}
}
@@ -291,10 +271,8 @@ constructor(
clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
}
- override fun onWeatherDataChanged(data: Weather?) {
- if (data != null) {
- clock?.events?.onWeatherDataChanged(data)
- }
+ override fun onWeatherDataChanged(data: WeatherData) {
+ clock?.events?.onWeatherDataChanged(data)
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index a25b281f807c..c5a06b48e015 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -24,7 +24,6 @@ import android.view.ViewConfiguration;
import android.widget.Button;
import com.android.internal.util.EmergencyAffordanceManager;
-import com.android.internal.widget.LockPatternUtils;
/**
* This class implements a smart emergency button that updates itself based
@@ -40,8 +39,6 @@ public class EmergencyButton extends Button {
private int mDownY;
private boolean mLongPressWasDragged;
- private LockPatternUtils mLockPatternUtils;
-
private final boolean mEnableEmergencyCallWhileSimLocked;
public EmergencyButton(Context context) {
@@ -58,7 +55,6 @@ public class EmergencyButton extends Button {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mLockPatternUtils = new LockPatternUtils(mContext);
if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
setOnLongClickListener(v -> {
if (!mLongPressWasDragged
@@ -95,7 +91,8 @@ public class EmergencyButton extends Button {
return super.performLongClick();
}
- void updateEmergencyCallButton(boolean isInCall, boolean hasTelephonyRadio, boolean simLocked) {
+ void updateEmergencyCallButton(boolean isInCall, boolean hasTelephonyRadio, boolean simLocked,
+ boolean isSecure) {
boolean visible = false;
if (hasTelephonyRadio) {
// Emergency calling requires a telephony radio.
@@ -107,7 +104,7 @@ public class EmergencyButton extends Button {
visible = mEnableEmergencyCallWhileSimLocked;
} else {
// Only show if there is a secure screen (pin/pattern/SIM pin/SIM puk);
- visible = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser());
+ visible = isSecure;
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
index ea808eb19b90..f7e8eb492584 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
@@ -18,6 +18,7 @@ package com.android.keyguard;
import static com.android.systemui.DejankUtils.whitelistIpcs;
+import android.annotation.SuppressLint;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.content.Intent;
@@ -31,16 +32,22 @@ import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.dagger.KeyguardBouncerScope;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.util.EmergencyDialerConstants;
import com.android.systemui.util.ViewController;
+import java.util.concurrent.Executor;
+
import javax.inject.Inject;
/** View Controller for {@link com.android.keyguard.EmergencyButton}. */
@@ -57,6 +64,9 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
private final MetricsLogger mMetricsLogger;
private EmergencyButtonCallback mEmergencyButtonCallback;
+ private LockPatternUtils mLockPatternUtils;
+ private Executor mMainExecutor;
+ private Executor mBackgroundExecutor;
private final KeyguardUpdateMonitorCallback mInfoCallback =
new KeyguardUpdateMonitorCallback() {
@@ -78,12 +88,15 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
}
};
- private EmergencyButtonController(@Nullable EmergencyButton view,
+ @VisibleForTesting
+ public EmergencyButtonController(@Nullable EmergencyButton view,
ConfigurationController configurationController,
KeyguardUpdateMonitor keyguardUpdateMonitor, TelephonyManager telephonyManager,
PowerManager powerManager, ActivityTaskManager activityTaskManager,
ShadeController shadeController,
- @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger) {
+ @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger,
+ LockPatternUtils lockPatternUtils,
+ Executor mainExecutor, Executor backgroundExecutor) {
super(view);
mConfigurationController = configurationController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -93,6 +106,9 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
mShadeController = shadeController;
mTelecomManager = telecomManager;
mMetricsLogger = metricsLogger;
+ mLockPatternUtils = lockPatternUtils;
+ mMainExecutor = mainExecutor;
+ mBackgroundExecutor = backgroundExecutor;
}
@Override
@@ -113,13 +129,27 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
mConfigurationController.removeCallback(mConfigurationListener);
}
- private void updateEmergencyCallButton() {
+ /**
+ * Updates the visibility of the emergency button.
+ *
+ * This method runs binder calls in a background thread.
+ */
+ @VisibleForTesting
+ @SuppressLint("MissingPermission")
+ public void updateEmergencyCallButton() {
if (mView != null) {
- mView.updateEmergencyCallButton(
- mTelecomManager != null && mTelecomManager.isInCall(),
- getContext().getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_TELEPHONY),
- mKeyguardUpdateMonitor.isSimPinVoiceSecure());
+ // Run in bg thread to avoid throttling the main thread with binder call.
+ mBackgroundExecutor.execute(() -> {
+ boolean isInCall = mTelecomManager != null && mTelecomManager.isInCall();
+ boolean isSecure = mLockPatternUtils
+ .isSecure(KeyguardUpdateMonitor.getCurrentUser());
+ mMainExecutor.execute(() -> mView.updateEmergencyCallButton(
+ /* isInCall= */ isInCall,
+ /* hasTelephonyRadio= */ getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_TELEPHONY),
+ /* simLocked= */ mKeyguardUpdateMonitor.isSimPinVoiceSecure(),
+ /* isSecure= */ isSecure));
+ });
}
}
@@ -129,6 +159,7 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
/**
* Shows the emergency dialer or returns the user to the existing call.
*/
+ @SuppressLint("MissingPermission")
public void takeEmergencyCallAction() {
mMetricsLogger.action(MetricsEvent.ACTION_EMERGENCY_CALL);
if (mPowerManager != null) {
@@ -136,29 +167,35 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
}
mActivityTaskManager.stopSystemLockTaskMode();
mShadeController.collapseShade(false);
- if (mTelecomManager != null && mTelecomManager.isInCall()) {
- mTelecomManager.showInCallScreen(false);
- if (mEmergencyButtonCallback != null) {
- mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall();
- }
- } else {
- mKeyguardUpdateMonitor.reportEmergencyCallAction(true /* bypassHandler */);
- if (mTelecomManager == null) {
- Log.wtf(LOG_TAG, "TelecomManager was null, cannot launch emergency dialer");
- return;
- }
- Intent emergencyDialIntent =
- mTelecomManager.createLaunchEmergencyDialerIntent(null /* number*/)
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_CLEAR_TOP)
- .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
- EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);
-
- getContext().startActivityAsUser(emergencyDialIntent,
- ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(),
- new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
- }
+ // Run in bg thread to avoid throttling the main thread with binder call.
+ mBackgroundExecutor.execute(() -> {
+ boolean isInCall = mTelecomManager != null && mTelecomManager.isInCall();
+ mMainExecutor.execute(() -> {
+ if (isInCall) {
+ mTelecomManager.showInCallScreen(false);
+ if (mEmergencyButtonCallback != null) {
+ mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall();
+ }
+ } else {
+ mKeyguardUpdateMonitor.reportEmergencyCallAction(true /* bypassHandler */);
+ if (mTelecomManager == null) {
+ Log.wtf(LOG_TAG, "TelecomManager was null, cannot launch emergency dialer");
+ return;
+ }
+ Intent emergencyDialIntent =
+ mTelecomManager.createLaunchEmergencyDialerIntent(null /* number*/)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
+ EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);
+
+ getContext().startActivityAsUser(emergencyDialIntent,
+ ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(),
+ new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
+ }
+ });
+ });
}
/** */
@@ -178,13 +215,19 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
@Nullable
private final TelecomManager mTelecomManager;
private final MetricsLogger mMetricsLogger;
+ private final LockPatternUtils mLockPatternUtils;
+ private final Executor mMainExecutor;
+ private final Executor mBackgroundExecutor;
@Inject
public Factory(ConfigurationController configurationController,
KeyguardUpdateMonitor keyguardUpdateMonitor, TelephonyManager telephonyManager,
PowerManager powerManager, ActivityTaskManager activityTaskManager,
ShadeController shadeController,
- @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger) {
+ @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger,
+ LockPatternUtils lockPatternUtils,
+ @Main Executor mainExecutor,
+ @Background Executor backgroundExecutor) {
mConfigurationController = configurationController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -194,14 +237,17 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
mShadeController = shadeController;
mTelecomManager = telecomManager;
mMetricsLogger = metricsLogger;
+ mLockPatternUtils = lockPatternUtils;
+ mMainExecutor = mainExecutor;
+ mBackgroundExecutor = backgroundExecutor;
}
/** Construct an {@link com.android.keyguard.EmergencyButtonController}. */
public EmergencyButtonController create(EmergencyButton view) {
return new EmergencyButtonController(view, mConfigurationController,
mKeyguardUpdateMonitor, mTelephonyManager, mPowerManager, mActivityTaskManager,
- mShadeController,
- mTelecomManager, mMetricsLogger);
+ mShadeController, mTelecomManager, mMetricsLogger, mLockPatternUtils,
+ mMainExecutor, mBackgroundExecutor);
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
index e0cf7b6a2bc4..d8085b9f9f2e 100644
--- a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+++ b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
@@ -132,6 +132,7 @@ private object InternalFaceAuthReasons {
/**
* UiEvents that are logged to identify why face auth is being triggered.
+ *
* @param extraInfo is logged as the position. See [UiEventLogger#logWithInstanceIdAndPosition]
*/
enum class FaceAuthUiEvent
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
index fe8b8c944d13..c98e9b40e7ab 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
@@ -40,7 +40,7 @@ data class KeyguardFaceListenModel(
var keyguardGoingAway: Boolean = false,
var listeningForFaceAssistant: Boolean = false,
var occludingAppRequestingFaceAuth: Boolean = false,
- val postureAllowsListening: Boolean = false,
+ var postureAllowsListening: Boolean = false,
var primaryUser: Boolean = false,
var secureCameraLaunched: Boolean = false,
var supportsDetect: Boolean = false,
@@ -70,6 +70,7 @@ data class KeyguardFaceListenModel(
listeningForFaceAssistant.toString(),
occludingAppRequestingFaceAuth.toString(),
primaryUser.toString(),
+ postureAllowsListening.toString(),
secureCameraLaunched.toString(),
supportsDetect.toString(),
switchingUser.toString(),
@@ -109,6 +110,7 @@ data class KeyguardFaceListenModel(
listeningForFaceAssistant = model.listeningForFaceAssistant
occludingAppRequestingFaceAuth = model.occludingAppRequestingFaceAuth
primaryUser = model.primaryUser
+ postureAllowsListening = model.postureAllowsListening
secureCameraLaunched = model.secureCameraLaunched
supportsDetect = model.supportsDetect
switchingUser = model.switchingUser
@@ -152,6 +154,7 @@ data class KeyguardFaceListenModel(
"listeningForFaceAssistant",
"occludingAppRequestingFaceAuth",
"primaryUser",
+ "postureAllowsListening",
"secureCameraLaunched",
"supportsDetect",
"switchingUser",
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index 67e3400670ba..03947542d21e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -217,9 +217,11 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
private void animate(float progress) {
Interpolator standardDecelerate = Interpolators.STANDARD_DECELERATE;
Interpolator legacyDecelerate = Interpolators.LEGACY_DECELERATE;
+ float standardProgress = standardDecelerate.getInterpolation(progress);
mBouncerMessageView.setTranslationY(
- mYTrans - mYTrans * standardDecelerate.getInterpolation(progress));
+ mYTrans - mYTrans * standardProgress);
+ mBouncerMessageView.setAlpha(standardProgress);
for (int i = 0; i < mViews.length; i++) {
View[] row = mViews[i];
@@ -236,7 +238,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
view.setAlpha(scaledProgress);
int yDistance = mYTrans + mYTransOffset * i;
view.setTranslationY(
- yDistance - (yDistance * standardDecelerate.getInterpolation(progress)));
+ yDistance - (yDistance * standardProgress));
if (view instanceof NumPadAnimationListener) {
((NumPadAnimationListener) view).setProgress(scaledProgress);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index c1fae9e44bd3..33bea027cd20 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -69,6 +69,7 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
private Interpolator mLinearOutSlowInInterpolator;
private Interpolator mFastOutLinearInInterpolator;
+ private DisappearAnimationListener mDisappearAnimationListener;
public KeyguardPasswordView(Context context) {
this(context, null);
@@ -186,9 +187,13 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
return;
}
Insets shownInsets = controller.getShownStateInsets();
- Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0,
- (int) (-shownInsets.bottom / 4
- * anim.getAnimatedFraction())));
+ int dist = (int) (-shownInsets.bottom / 4
+ * anim.getAnimatedFraction());
+ Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0, dist));
+ if (mDisappearAnimationListener != null) {
+ mDisappearAnimationListener.setTranslationY(-dist);
+ }
+
controller.setInsetsAndAlpha(insets,
(float) animation.getAnimatedValue(),
anim.getAnimatedFraction());
@@ -209,6 +214,7 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
controller.finish(false);
runOnFinishImeAnimationRunnable();
finishRunnable.run();
+ mDisappearAnimationListener = null;
Trace.endSection();
});
}
@@ -286,4 +292,19 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
}
});
}
+
+ /**
+ * Listens to the progress of the disappear animation and handles it.
+ */
+ interface DisappearAnimationListener {
+ void setTranslationY(int transY);
+ }
+
+ /**
+ * Set an instance of the disappear animation listener to this class. This will be
+ * removed when the animation completes.
+ */
+ public void setDisappearAnimationListener(DisappearAnimationListener listener) {
+ mDisappearAnimationListener = listener;
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
index d221e22a4fcd..a010c9a16517 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
@@ -26,6 +26,7 @@ import android.text.method.TextKeyListener;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
+import android.view.WindowInsets;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -156,6 +157,15 @@ public class KeyguardPasswordViewController
// TODO: Remove this workaround by ensuring such a race condition never happens.
mMainExecutor.executeDelayed(
this::updateSwitchImeButton, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON);
+ mView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
+ @Override
+ public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
+ if (!mKeyguardViewController.isBouncerShowing()) {
+ mView.hideKeyboard();
+ }
+ return insets;
+ }
+ });
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index eec788b7add8..ba5a8c94dc23 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -174,6 +174,17 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
private @Mode int mCurrentMode = MODE_UNINITIALIZED;
private int mWidth = -1;
+ /**
+ * This callback is used to animate KeyguardSecurityContainer and its child views based on
+ * the interaction with the ime. After
+ * {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)},
+ * {@link #onApplyWindowInsets} is called where we
+ * set the bottom padding to be the height of the keyboard. We use this padding to determine
+ * the delta of vertical distance for y-translation animations.
+ * Note that bottom padding is not set when the disappear animation is started because
+ * we are deferring the y translation logic to the animator in
+ * {@link KeyguardPasswordView#startDisappearAnimation(Runnable)}
+ */
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
@@ -214,7 +225,6 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
continue;
}
interpolatedFraction = animation.getInterpolatedFraction();
-
final int paddingBottom = (int) MathUtils.lerp(
start, end,
interpolatedFraction);
@@ -492,12 +502,14 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(event);
int pointerIndex = event.findPointerIndex(mActivePointerId);
- float y = event.getY(pointerIndex);
- if (mLastTouchY != -1) {
- float dy = y - mLastTouchY;
- setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER);
+ if (pointerIndex != -1) {
+ float y = event.getY(pointerIndex);
+ if (mLastTouchY != -1) {
+ float dy = y - mLastTouchY;
+ setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER);
+ }
+ mLastTouchY = y;
}
- mLastTouchY = y;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
@@ -567,13 +579,21 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
*/
public void startDisappearAnimation(SecurityMode securitySelection) {
mDisappearAnimRunning = true;
- mViewMode.startDisappearAnimation(securitySelection);
+ if (securitySelection == SecurityMode.Password
+ && mSecurityViewFlipper.getSecurityView() instanceof KeyguardPasswordView) {
+ ((KeyguardPasswordView) mSecurityViewFlipper.getSecurityView())
+ .setDisappearAnimationListener(this::setTranslationY);
+ } else {
+ mViewMode.startDisappearAnimation(securitySelection);
+ }
}
/**
* This will run when the bouncer shows in all cases except when the user drags the bouncer up.
*/
public void startAppearAnimation(SecurityMode securityMode) {
+ setTranslationY(0f);
+ setAlpha(1f);
updateChildren(0 /* translationY */, 1f /* alpha */);
mViewMode.startAppearAnimation(securityMode);
}
@@ -622,7 +642,13 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
int inset = max(bottomInset, imeInset);
int paddingBottom = max(inset, getContext().getResources()
.getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin));
- setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom);
+ // If security mode is password, we rely on the animation value of defined in
+ // KeyguardPasswordView to determine the y translation animation.
+ // This means that we will prevent the WindowInsetsAnimationCallback from setting any y
+ // translation values by preventing the setting of the padding here.
+ if (!mDisappearAnimRunning) {
+ setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom);
+ }
return insets.inset(0, 0, 0, inset);
}
@@ -1044,7 +1070,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
AnimatorSet anims = new AnimatorSet();
ObjectAnimator yAnim = ObjectAnimator.ofFloat(mView, View.TRANSLATION_Y, yTranslation);
- ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mView, View.ALPHA, 0f);
+ ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mUserSwitcherViewGroup, View.ALPHA,
+ 0f);
anims.setInterpolator(Interpolators.STANDARD_ACCELERATE);
anims.playTogether(alphaAnim, yAnim);
@@ -1198,8 +1225,7 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
constraintSet.connect(rightElement, LEFT, leftElement, RIGHT);
constraintSet.connect(rightElement, RIGHT, PARENT_ID, RIGHT);
constraintSet.connect(mUserSwitcherViewGroup.getId(), TOP, PARENT_ID, TOP);
- constraintSet.connect(mUserSwitcherViewGroup.getId(), BOTTOM, PARENT_ID, BOTTOM,
- yTrans);
+ constraintSet.connect(mUserSwitcherViewGroup.getId(), BOTTOM, PARENT_ID, BOTTOM);
constraintSet.connect(mViewFlipper.getId(), TOP, PARENT_ID, TOP);
constraintSet.connect(mViewFlipper.getId(), BOTTOM, PARENT_ID, BOTTOM);
constraintSet.setHorizontalChainStyle(mUserSwitcherViewGroup.getId(), CHAIN_SPREAD);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 92cbb296f270..2c2caea60f5a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -17,7 +17,6 @@
package com.android.keyguard;
import static android.app.StatusBarManager.SESSION_KEYGUARD;
-import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_BIOMETRIC;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_EXTENDED_ACCESS;
@@ -36,7 +35,6 @@ import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricOverlayConstants;
-import android.hardware.biometrics.BiometricSourceType;
import android.media.AudioManager;
import android.metrics.LogMaker;
import android.os.SystemClock;
@@ -129,6 +127,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
private View.OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event);
private ActivityStarter.OnDismissAction mDismissAction;
private Runnable mCancelAction;
+ private boolean mWillRunDismissFromKeyguard;
private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
@@ -264,8 +263,10 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
// If there's a pending runnable because the user interacted with a widget
// and we're leaving keyguard, then run it.
boolean deferKeyguardDone = false;
+ mWillRunDismissFromKeyguard = false;
if (mDismissAction != null) {
deferKeyguardDone = mDismissAction.onDismiss();
+ mWillRunDismissFromKeyguard = mDismissAction.willRunAnimationOnKeyguard();
mDismissAction = null;
mCancelAction = null;
}
@@ -320,7 +321,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
KeyguardSecurityContainerController.this.onDensityOrFontScaleChanged();
}
};
- private boolean mBouncerVisible = false;
private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -355,19 +355,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
public void onDevicePolicyManagerStateChanged() {
showPrimarySecurityScreen(false);
}
-
- @Override
- public void onBiometricRunningStateChanged(boolean running,
- BiometricSourceType biometricSourceType) {
- if (biometricSourceType == FINGERPRINT) {
- updateSideFpsVisibility();
- }
- }
-
- @Override
- public void onStrongAuthStateChanged(int userId) {
- updateSideFpsVisibility();
- }
};
@Inject
@@ -459,35 +446,24 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
getCurrentSecurityController().onPause();
}
mView.onPause();
- // It might happen that onStartingToHide is not called when the device is locked while on
- // bouncer.
- setBouncerVisible(false);
mView.clearFocus();
}
- private void updateSideFpsVisibility() {
+ /**
+ * Shows and hides the side finger print sensor animation.
+ *
+ * @param isVisible sets whether we show or hide the side fps animation
+ */
+ public void updateSideFpsVisibility(boolean isVisible) {
if (!mSideFpsController.isPresent()) {
return;
}
- final boolean sfpsEnabled = getResources().getBoolean(
- R.bool.config_show_sidefps_hint_on_bouncer);
- final boolean fpsDetectionRunning = mUpdateMonitor.isFingerprintDetectionRunning();
- final boolean isUnlockingWithFpAllowed =
- mUpdateMonitor.isUnlockingWithFingerprintAllowed();
-
- boolean toShow = mBouncerVisible && sfpsEnabled && fpsDetectionRunning
- && isUnlockingWithFpAllowed;
- if (DEBUG) {
- Log.d(TAG, "sideFpsToShow=" + toShow + ", "
- + "mBouncerVisible=" + mBouncerVisible + ", "
- + "configEnabled=" + sfpsEnabled + ", "
- + "fpsDetectionRunning=" + fpsDetectionRunning + ", "
- + "isUnlockingWithFpAllowed=" + isUnlockingWithFpAllowed);
- }
- if (toShow) {
- mSideFpsController.get().show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
+ if (isVisible) {
+ mSideFpsController.get().show(
+ SideFpsUiRequestSource.PRIMARY_BOUNCER,
+ BiometricOverlayConstants.REASON_AUTH_KEYGUARD
+ );
} else {
mSideFpsController.get().hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
}
@@ -553,6 +529,13 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
}
/**
+ * @return will the dismissal run from the keyguard layout (instead of from bouncer)
+ */
+ public boolean willRunDismissFromKeyguard() {
+ return mWillRunDismissFromKeyguard;
+ }
+
+ /**
* Remove any dismiss action or cancel action that was set.
*/
public void cancelDismissAction() {
@@ -636,7 +619,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, state);
getCurrentSecurityController().onResume(reason);
- updateSideFpsVisibility();
}
mView.onResume(
mSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser()),
@@ -664,12 +646,17 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
public void startAppearAnimation() {
if (mCurrentSecurityMode != SecurityMode.None) {
- mView.setAlpha(1f);
+ setAlpha(1f);
mView.startAppearAnimation(mCurrentSecurityMode);
getCurrentSecurityController().startAppearAnimation();
}
}
+ /** Set the alpha of the security container view */
+ public void setAlpha(float alpha) {
+ mView.setAlpha(alpha);
+ }
+
public boolean startDisappearAnimation(Runnable onFinishRunnable) {
boolean didRunAnimation = false;
@@ -690,22 +677,15 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
if (mCurrentSecurityMode != SecurityMode.None) {
getCurrentSecurityController().onStartingToHide();
}
- setBouncerVisible(false);
}
/** Called when the bouncer changes visibility. */
- public void onBouncerVisibilityChanged(@View.Visibility int visibility) {
- setBouncerVisible(visibility == View.VISIBLE);
- if (visibility == View.INVISIBLE) {
+ public void onBouncerVisibilityChanged(boolean isVisible) {
+ if (!isVisible) {
mView.resetScale();
}
}
- private void setBouncerVisible(boolean visible) {
- mBouncerVisible = visible;
- updateSideFpsVisibility();
- }
-
/**
* Shows the next security screen if there is one.
* @param authenticated true if the user entered the correct authentication
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index b53b868025e8..f4c581552bc4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -21,8 +21,6 @@ import android.util.Slog;
import com.android.keyguard.KeyguardClockSwitch.ClockSize;
import com.android.keyguard.logging.KeyguardLogger;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.ClockAnimations;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
@@ -62,7 +60,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
KeyguardUpdateMonitor keyguardUpdateMonitor,
ConfigurationController configurationController,
DozeParameters dozeParameters,
- FeatureFlags featureFlags,
ScreenOffAnimationController screenOffAnimationController,
KeyguardLogger logger) {
super(keyguardStatusView);
@@ -73,8 +70,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController,
dozeParameters, screenOffAnimationController, /* animateYPos= */ true,
logger.getBuffer());
- mKeyguardVisibilityHelper.setOcclusionTransitionFlagEnabled(
- featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION));
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index be9264dbfcf3..1ccde322628a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -73,11 +73,9 @@ import static com.android.systemui.statusbar.policy.DevicePostureController.DEVI
import android.annotation.AnyThread;
import android.annotation.MainThread;
import android.annotation.SuppressLint;
-import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.AlarmManager;
-import android.app.UserSwitchObserver;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
@@ -104,7 +102,6 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.nfc.NfcAdapter;
import android.os.CancellationSignal;
import android.os.Handler;
-import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
@@ -148,7 +145,7 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.dump.DumpsysTableLogger;
import com.android.systemui.log.SessionTracker;
-import com.android.systemui.plugins.Weather;
+import com.android.systemui.plugins.WeatherData;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -156,6 +153,7 @@ import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.DevicePostureController;
+import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.Assert;
import com.android.systemui.util.settings.SecureSettings;
@@ -175,6 +173,7 @@ import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.TimeZone;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
@@ -361,7 +360,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private final FaceManager mFaceManager;
private final LockPatternUtils mLockPatternUtils;
@VisibleForTesting
- @DevicePostureController.DevicePostureInt
+ @DevicePostureInt
protected int mConfigFaceAuthSupportedPosture;
private KeyguardBypassController mKeyguardBypassController;
@@ -678,7 +677,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
public void onTrustManagedChanged(boolean managed, int userId) {
Assert.isMainThread();
mUserTrustIsManaged.put(userId, managed);
- mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
+ boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userId);
+ mLogger.logTrustUsuallyManagedUpdated(userId, mUserTrustIsUsuallyManaged.get(userId),
+ trustUsuallyManaged, "onTrustManagedChanged");
+ mUserTrustIsUsuallyManaged.put(userId, trustUsuallyManaged);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -706,6 +708,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (mKeyguardGoingAway) {
updateFaceListeningState(BIOMETRIC_ACTION_STOP,
FACE_AUTH_STOPPED_KEYGUARD_GOING_AWAY);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onKeyguardGoingAway();
+ }
+ }
}
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
}
@@ -816,6 +824,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
+ private void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+ boolean isStrongBiometric) {
+ Assert.isMainThread();
+ Trace.beginSection("KeyGuardUpdateMonitor#onBiometricDetected");
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onBiometricDetected(userId, biometricSourceType, isStrongBiometric);
+ }
+ }
+ Trace.endSection();
+ }
+
@VisibleForTesting
protected void onFingerprintAuthenticated(int userId, boolean isStrongBiometric) {
Assert.isMainThread();
@@ -853,7 +874,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private void reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId) {
mBackgroundExecutor.execute(
- () -> mLockPatternUtils.reportSuccessfulBiometricUnlock(isStrongBiometric, userId));
+ () -> {
+ mLogger.logReportSuccessfulBiometricUnlock(isStrongBiometric, userId);
+ mLockPatternUtils.reportSuccessfulBiometricUnlock(isStrongBiometric, userId);
+ });
}
private void handleFingerprintAuthFailed() {
@@ -892,6 +916,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
+ private void handleBiometricDetected(int authUserId, BiometricSourceType biometricSourceType,
+ boolean isStrongBiometric) {
+ Trace.beginSection("KeyGuardUpdateMonitor#handlerBiometricDetected");
+ onBiometricDetected(authUserId, biometricSourceType, isStrongBiometric);
+ if (biometricSourceType == FINGERPRINT) {
+ mLogger.logFingerprintDetected(authUserId, isStrongBiometric);
+ } else if (biometricSourceType == FACE) {
+ mLogger.logFaceDetected(authUserId, isStrongBiometric);
+ setFaceRunningState(BIOMETRIC_STATE_STOPPED);
+ }
+
+ Trace.endSection();
+ }
+
private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) {
Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
@@ -943,8 +981,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private void onFingerprintCancelNotReceived() {
mLogger.e("Fp cancellation not received, transitioning to STOPPED");
+ final boolean wasCancellingRestarting = mFingerprintRunningState
+ == BIOMETRIC_STATE_CANCELLING_RESTARTING;
mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
- KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
+ if (wasCancellingRestarting) {
+ KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
+ } else {
+ KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
+ }
}
private void handleFingerprintError(int msgId, String errString) {
@@ -1031,6 +1075,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
() -> updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE),
getBiometricLockoutDelay());
} else {
+ boolean temporaryLockoutReset = wasLockout && !mFingerprintLockedOut;
+ if (temporaryLockoutReset) {
+ mLogger.d("temporaryLockoutReset - stopListeningForFingerprint() to stop"
+ + " detectFingerprint");
+ stopListeningForFingerprint();
+ }
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
}
@@ -1730,10 +1780,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
};
+ private final FingerprintManager.FingerprintDetectionCallback mFingerprintDetectionCallback =
+ (sensorId, userId, isStrongBiometric) -> {
+ // Trigger the fingerprint detected path so the bouncer can be shown
+ handleBiometricDetected(userId, FINGERPRINT, isStrongBiometric);
+ };
+
private final FaceManager.FaceDetectionCallback mFaceDetectionCallback
= (sensorId, userId, isStrongBiometric) -> {
- // Trigger the face success path so the bouncer can be shown
- handleFaceAuthenticated(userId, isStrongBiometric);
+ // Trigger the face detected path so the bouncer can be shown
+ handleBiometricDetected(userId, FACE, isStrongBiometric);
};
@VisibleForTesting
@@ -1797,10 +1853,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final DevicePostureController.Callback mPostureCallback =
new DevicePostureController.Callback() {
@Override
- public void onPostureChanged(int posture) {
+ public void onPostureChanged(@DevicePostureInt int posture) {
+ boolean currentPostureAllowsFaceAuth = doesPostureAllowFaceAuth(mPostureState);
+ boolean newPostureAllowsFaceAuth = doesPostureAllowFaceAuth(posture);
mPostureState = posture;
- updateFaceListeningState(BIOMETRIC_ACTION_UPDATE,
- FACE_AUTH_UPDATED_POSTURE_CHANGED);
+ if (currentPostureAllowsFaceAuth && !newPostureAllowsFaceAuth) {
+ mLogger.d("New posture does not allow face auth, stopping it");
+ updateFaceListeningState(BIOMETRIC_ACTION_STOP,
+ FACE_AUTH_UPDATED_POSTURE_CHANGED);
+ }
}
};
@@ -2158,7 +2219,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
handleDevicePolicyManagerStateChanged(msg.arg1);
break;
case MSG_USER_SWITCHING:
- handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
+ handleUserSwitching(msg.arg1, (CountDownLatch) msg.obj);
break;
case MSG_USER_SWITCH_COMPLETE:
handleUserSwitchComplete(msg.arg1);
@@ -2283,11 +2344,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mHandler, UserHandle.ALL);
mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
- try {
- ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
+ mUserTracker.addCallback(mUserChangedCallback, mainExecutor);
mTrustManager.registerTrustListener(this);
@@ -2333,8 +2390,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
updateSecondaryLockscreenRequirement(user);
List<UserInfo> allUsers = mUserManager.getUsers();
for (UserInfo userInfo : allUsers) {
+ boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userInfo.id);
+ mLogger.logTrustUsuallyManagedUpdated(userInfo.id,
+ mUserTrustIsUsuallyManaged.get(userInfo.id),
+ trustUsuallyManaged, "init from constructor");
mUserTrustIsUsuallyManaged.put(userInfo.id,
- mTrustManager.isTrustUsuallyManaged(userInfo.id));
+ trustUsuallyManaged);
}
updateAirplaneModeState();
@@ -2374,10 +2435,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
private void updateFaceEnrolled(int userId) {
- mIsFaceEnrolled = whitelistIpcs(
+ Boolean isFaceEnrolled = whitelistIpcs(
() -> mFaceManager != null && mFaceManager.isHardwareDetected()
&& mFaceManager.hasEnrolledTemplates(userId)
&& mBiometricEnabledForUser.get(userId));
+ if (mIsFaceEnrolled != isFaceEnrolled) {
+ mLogger.logFaceEnrolledUpdated(mIsFaceEnrolled, isFaceEnrolled);
+ }
+ mIsFaceEnrolled = isFaceEnrolled;
}
public boolean isFaceSupported() {
@@ -2423,17 +2488,17 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return mIsFaceEnrolled;
}
- private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() {
+ private final UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() {
@Override
- public void onUserSwitching(int newUserId, IRemoteCallback reply) {
+ public void onUserChanging(int newUser, Context userContext, CountDownLatch latch) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
- newUserId, 0, reply));
+ newUser, 0, latch));
}
@Override
- public void onUserSwitchComplete(int newUserId) {
+ public void onUserChanged(int newUser, Context userContext) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
- newUserId, 0));
+ newUser, 0));
}
};
@@ -2456,11 +2521,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// If this message exists, we should not authenticate again until this message is
// consumed by the handler
if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
+ mLogger.logHandlerHasAuthContinueMsgs(action);
return;
}
// don't start running fingerprint until they're registered
if (!mAuthController.areAllFingerprintAuthenticatorsRegistered()) {
+ mLogger.d("All FP authenticators not registered, skipping FP listening state update");
return;
}
final boolean shouldListenForFingerprint = shouldListenForFingerprint(isUdfpsSupported());
@@ -2833,9 +2900,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user);
final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant();
final boolean isUdfpsFingerDown = mAuthController.isUdfpsFingerDown();
- final boolean isPostureAllowedForFaceAuth =
- mConfigFaceAuthSupportedPosture == 0 /* DEVICE_POSTURE_UNKNOWN */ ? true
- : (mPostureState == mConfigFaceAuthSupportedPosture);
+ final boolean isPostureAllowedForFaceAuth = doesPostureAllowFaceAuth(mPostureState);
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
final boolean shouldListen =
@@ -2884,6 +2949,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return shouldListen;
}
+ private boolean doesPostureAllowFaceAuth(@DevicePostureInt int posture) {
+ return mConfigFaceAuthSupportedPosture == DEVICE_POSTURE_UNKNOWN
+ || (posture == mConfigFaceAuthSupportedPosture);
+ }
+
private void logListenerModelData(@NonNull KeyguardListenModel model) {
mLogger.logKeyguardListenerModel(model);
if (model instanceof KeyguardFingerprintListenModel) {
@@ -2920,11 +2990,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mLogger.v("startListeningForFingerprint - detect");
mFpm.detectFingerprint(
mFingerprintCancelSignal,
- (sensorId, user, isStrongBiometric) -> {
- mLogger.d("fingerprint detected");
- // Trigger the fingerprint success path so the bouncer can be shown
- handleFingerprintAuthenticated(user, isStrongBiometric);
- },
+ mFingerprintDetectionCallback,
userId);
} else {
mLogger.v("startListeningForFingerprint - authenticate");
@@ -3036,8 +3102,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@VisibleForTesting
boolean isUnlockWithFingerprintPossible(int userId) {
// TODO (b/242022358), make this rely on onEnrollmentChanged event and update it only once.
- mIsUnlockWithFingerprintPossible.put(userId, mFpm != null && mFpm.isHardwareDetected()
- && !isFingerprintDisabled(userId) && mFpm.hasEnrolledTemplates(userId));
+ boolean newFpEnrolled = mFpm != null && mFpm.isHardwareDetected()
+ && !isFingerprintDisabled(userId) && mFpm.hasEnrolledTemplates(userId);
+ Boolean oldFpEnrolled = mIsUnlockWithFingerprintPossible.getOrDefault(userId, false);
+ if (oldFpEnrolled != newFpEnrolled) {
+ mLogger.logFpEnrolledUpdated(userId, oldFpEnrolled, newFpEnrolled);
+ }
+ mIsUnlockWithFingerprintPossible.put(userId, newFpEnrolled);
return mIsUnlockWithFingerprintPossible.get(userId);
}
@@ -3150,21 +3221,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
* Handle {@link #MSG_USER_SWITCHING}
*/
@VisibleForTesting
- void handleUserSwitching(int userId, IRemoteCallback reply) {
+ void handleUserSwitching(int userId, CountDownLatch latch) {
Assert.isMainThread();
clearBiometricRecognized();
- mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
+ boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userId);
+ mLogger.logTrustUsuallyManagedUpdated(userId, mUserTrustIsUsuallyManaged.get(userId),
+ trustUsuallyManaged, "userSwitching");
+ mUserTrustIsUsuallyManaged.put(userId, trustUsuallyManaged);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onUserSwitching(userId);
}
}
- try {
- reply.sendResult(null);
- } catch (RemoteException e) {
- mLogger.logException(e, "Ignored exception while userSwitching");
- }
+ latch.countDown();
}
/**
@@ -3285,12 +3355,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
/**
* @param data the weather data (temp, conditions, unit) for weather clock to use
*/
- public void sendWeatherData(Weather data) {
+ public void sendWeatherData(WeatherData data) {
mHandler.post(()-> {
handleWeatherDataUpdate(data); });
}
- private void handleWeatherDataUpdate(Weather data) {
+ private void handleWeatherDataUpdate(WeatherData data) {
Assert.isMainThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -3305,8 +3375,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
*/
private void handleBatteryUpdate(BatteryStatus status) {
Assert.isMainThread();
- mLogger.d("handleBatteryUpdate");
final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
+ mLogger.logHandleBatteryUpdate(batteryUpdateInteresting);
mBatteryStatus = status;
if (batteryUpdateInteresting) {
for (int i = 0; i < mCallbacks.size(); i++) {
@@ -3583,7 +3653,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
* Register to receive notifications about general keyguard information
* (see {@link KeyguardUpdateMonitorCallback}.
*
- * @param callback The callback to register
+ * @param callback The callback to register. Stay away from passing anonymous instances
+ * as they will likely be dereferenced. Ensure that the callback is a class
+ * field to persist it.
*/
public void registerCallback(KeyguardUpdateMonitorCallback callback) {
Assert.isMainThread();
@@ -3934,13 +4006,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mContext.getContentResolver().unregisterContentObserver(mTimeFormatChangeObserver);
}
- try {
- ActivityManager.getService().unregisterUserSwitchObserver(mUserSwitchObserver);
- } catch (RemoteException e) {
- mLogger.logException(
- e,
- "RemoteException onDestroy. cannot unregister userSwitchObserver");
- }
+ mUserTracker.removeCallback(mUserChangedCallback);
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 0da799e0964d..feff216310df 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -23,7 +23,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settingslib.fuelgauge.BatteryStatus;
-import com.android.systemui.plugins.Weather;
+import com.android.systemui.plugins.WeatherData;
import com.android.systemui.statusbar.KeyguardIndicationController;
import java.util.TimeZone;
@@ -61,7 +61,7 @@ public class KeyguardUpdateMonitorCallback {
/**
* Called when receive new weather data.
*/
- public void onWeatherDataChanged(Weather data) { }
+ public void onWeatherDataChanged(WeatherData data) { }
/**
* Called when the carrier PLMN or SPN changes.
@@ -214,7 +214,7 @@ public class KeyguardUpdateMonitorCallback {
public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) { }
/**
- * Called when a biometric is recognized.
+ * Called when a biometric is authenticated.
* @param userId the user id for which the biometric sample was authenticated
* @param biometricSourceType
*/
@@ -222,6 +222,14 @@ public class KeyguardUpdateMonitorCallback {
boolean isStrongBiometric) { }
/**
+ * Called when a biometric is detected but not successfully authenticated.
+ * @param userId the user id for which the biometric sample was detected
+ * @param biometricSourceType
+ */
+ public void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+ boolean isStrongBiometric) { }
+
+ /**
* Called when biometric authentication provides help string (e.g. "Try again")
* @param msgId
* @param helpString
@@ -309,4 +317,9 @@ public class KeyguardUpdateMonitorCallback {
* Called when the non-strong biometric state changed.
*/
public void onNonStrongBiometricAllowedChanged(int userId) { }
+
+ /**
+ * Called when keyguard is going away or not going away.
+ */
+ public void onKeyguardGoingAway() { }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
index 6c3c246e7fb9..7661b8d0c144 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
@@ -168,7 +168,7 @@ public interface KeyguardViewController {
/**
* Stop showing the alternate bouncer, if showing.
*/
- void hideAlternateBouncer(boolean forceUpdateScrim);
+ void hideAlternateBouncer(boolean updateScrim);
// TODO: Deprecate registerStatusBar in KeyguardViewController interface. It is currently
// only used for testing purposes in StatusBarKeyguardViewManager, and it prevents us from
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
index 7e48193bfc62..a678edc0eb06 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
@@ -28,7 +28,6 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -49,7 +48,6 @@ public class KeyguardVisibilityHelper {
private boolean mAnimateYPos;
private boolean mKeyguardViewVisibilityAnimating;
private boolean mLastOccludedState = false;
- private boolean mIsUnoccludeTransitionFlagEnabled = false;
private final AnimationProperties mAnimationProperties = new AnimationProperties();
private final LogBuffer mLogBuffer;
@@ -77,10 +75,6 @@ public class KeyguardVisibilityHelper {
return mKeyguardViewVisibilityAnimating;
}
- public void setOcclusionTransitionFlagEnabled(boolean enabled) {
- mIsUnoccludeTransitionFlagEnabled = enabled;
- }
-
/**
* Set the visibility of a keyguard view based on some new state.
*/
@@ -156,24 +150,9 @@ public class KeyguardVisibilityHelper {
// since it may need to be cancelled due to keyguard lifecycle events.
mScreenOffAnimationController.animateInKeyguard(
mView, mAnimateKeyguardStatusViewVisibleEndRunnable);
- } else if (!mIsUnoccludeTransitionFlagEnabled && mLastOccludedState && !isOccluded) {
- // An activity was displayed over the lock screen, and has now gone away
- log("Unoccluded transition");
- mView.setVisibility(View.VISIBLE);
- mView.setAlpha(0f);
-
- mView.animate()
- .setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .alpha(1f)
- .withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable)
- .start();
} else {
log("Direct set Visibility to VISIBLE");
mView.setVisibility(View.VISIBLE);
- if (!mIsUnoccludeTransitionFlagEnabled) {
- mView.setAlpha(1f);
- }
}
} else {
log("Direct set Visibility to GONE");
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
index b30a0e010e4b..ad669099284f 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
@@ -51,7 +51,6 @@ class NumPadAnimator {
private float mStartRadius;
private float mEndRadius;
private int mHeight;
- private boolean mInitialized;
private static final int EXPAND_ANIMATION_MS = 100;
private static final int EXPAND_COLOR_ANIMATION_MS = 50;
@@ -93,15 +92,15 @@ class NumPadAnimator {
}
void onLayout(int height) {
+ boolean shouldUpdateHeight = height != mHeight;
mHeight = height;
mStartRadius = height / 2f;
mEndRadius = height / 4f;
mExpandAnimator.setFloatValues(mStartRadius, mEndRadius);
mContractAnimator.setFloatValues(mEndRadius, mStartRadius);
// Set initial corner radius.
- if (!mInitialized) {
+ if (shouldUpdateHeight) {
mBackground.setCornerRadius(mStartRadius);
- mInitialized = true;
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index 0a4880e1ce66..3b0644eaab82 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -33,7 +33,6 @@ import android.widget.TextView;
import androidx.annotation.Nullable;
-import com.android.internal.widget.LockPatternUtils;
import com.android.settingslib.Utils;
import com.android.systemui.R;
@@ -46,7 +45,6 @@ public class NumPadKey extends ViewGroup implements NumPadAnimationListener {
private final TextView mDigitText;
private final TextView mKlondikeText;
- private final LockPatternUtils mLockPatternUtils;
private final PowerManager mPM;
private int mDigit = -1;
@@ -107,7 +105,6 @@ public class NumPadKey extends ViewGroup implements NumPadAnimationListener {
setOnHoverListener(new LiftToActivateListener(
(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE)));
- mLockPatternUtils = new LockPatternUtils(context);
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt
index bc0bd8c53d26..20f90072161b 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt
@@ -16,6 +16,7 @@
package com.android.keyguard.logging
+import android.hardware.biometrics.BiometricSourceType
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.dagger.BiometricLog
import com.android.systemui.plugins.log.LogBuffer
@@ -157,6 +158,36 @@ class BiometricUnlockLogger @Inject constructor(@BiometricLog private val logBuf
}
)
}
+
+ fun deferringAuthenticationDueToSleep(
+ userId: Int,
+ biometricSourceType: BiometricSourceType,
+ alreadyPendingAuth: Boolean
+ ) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = userId
+ str1 = biometricSourceType.name
+ bool2 = alreadyPendingAuth
+ },
+ {
+ "onBiometricAuthenticated, deferring auth: userId: $int1, " +
+ "biometricSourceType: $str1, " +
+ "goingToSleep: true, " +
+ "mPendingAuthentication != null: $bool2"
+ }
+ )
+ }
+
+ fun finishedGoingToSleepWithPendingAuth() {
+ logBuffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ "onFinishedGoingToSleep with pendingAuthenticated != null"
+ )
+ }
}
private fun wakeAndUnlockModeToString(mode: Int): String {
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
index 379c78ad8d0e..4d71a8952021 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
@@ -16,6 +16,7 @@
package com.android.keyguard.logging
+import com.android.systemui.biometrics.AuthRippleController
import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController
import com.android.systemui.log.dagger.KeyguardLog
import com.android.systemui.plugins.log.LogBuffer
@@ -96,6 +97,21 @@ constructor(
)
}
+ fun logUpdateBatteryIndication(
+ powerIndication: String,
+ pluggedIn: Boolean,
+ ) {
+ buffer.log(
+ KeyguardIndicationController.TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = powerIndication
+ bool1 = pluggedIn
+ },
+ { "updateBatteryIndication powerIndication:$str1 pluggedIn:$bool1" }
+ )
+ }
+
fun logKeyguardSwitchIndication(
type: Int,
message: String?,
@@ -111,6 +127,28 @@ constructor(
)
}
+ fun logRefreshBatteryInfo(
+ isChargingOrFull: Boolean,
+ powerPluggedIn: Boolean,
+ batteryLevel: Int,
+ batteryOverheated: Boolean
+ ) {
+ buffer.log(
+ KeyguardIndicationController.TAG,
+ LogLevel.DEBUG,
+ {
+ bool1 = isChargingOrFull
+ bool2 = powerPluggedIn
+ bool3 = batteryOverheated
+ int1 = batteryLevel
+ },
+ {
+ "refreshBatteryInfo isChargingOrFull:$bool1 powerPluggedIn:$bool2" +
+ " batteryOverheated:$bool3 batteryLevel:$int1"
+ }
+ )
+ }
+
fun getKeyguardSwitchIndicationNonSensitiveLog(type: Int, message: String?): String {
// only show the battery string. other strings may contain sensitive info
return if (type == KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY) {
@@ -120,4 +158,29 @@ constructor(
"type=${KeyguardIndicationRotateTextViewController.indicationTypeToString(type)}"
}
}
+
+ fun notShowingUnlockRipple(keyguardNotShowing: Boolean, unlockNotAllowed: Boolean) {
+ buffer.log(
+ AuthRippleController.TAG,
+ LogLevel.DEBUG,
+ {
+ bool1 = keyguardNotShowing
+ bool2 = unlockNotAllowed
+ },
+ { "Not showing unlock ripple: keyguardNotShowing: $bool1, unlockNotAllowed: $bool2" }
+ )
+ }
+
+ fun showingUnlockRippleAt(x: Int, y: Int, context: String) {
+ buffer.log(
+ AuthRippleController.TAG,
+ LogLevel.DEBUG,
+ {
+ int1 = x
+ int2 = y
+ str1 = context
+ },
+ { "Showing unlock ripple with center (x, y): ($int1, $int2), context: $str1" }
+ )
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index c414c088529c..51628076953b 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -26,6 +26,7 @@ import com.android.keyguard.FaceAuthUiEvent
import com.android.keyguard.KeyguardListenModel
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.keyguard.TrustGrantFlags
+import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.plugins.log.LogLevel.DEBUG
@@ -33,18 +34,15 @@ import com.android.systemui.plugins.log.LogLevel.ERROR
import com.android.systemui.plugins.log.LogLevel.INFO
import com.android.systemui.plugins.log.LogLevel.VERBOSE
import com.android.systemui.plugins.log.LogLevel.WARNING
-import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
import com.google.errorprone.annotations.CompileTimeConstant
import javax.inject.Inject
private const val TAG = "KeyguardUpdateMonitorLog"
-/**
- * Helper class for logging for [com.android.keyguard.KeyguardUpdateMonitor]
- */
-class KeyguardUpdateMonitorLogger @Inject constructor(
- @KeyguardUpdateMonitorLog private val logBuffer: LogBuffer
-) {
+/** Helper class for logging for [com.android.keyguard.KeyguardUpdateMonitor] */
+class KeyguardUpdateMonitorLogger
+@Inject
+constructor(@KeyguardUpdateMonitorLog private val logBuffer: LogBuffer) {
fun d(@CompileTimeConstant msg: String) = log(msg, DEBUG)
fun e(@CompileTimeConstant msg: String) = log(msg, ERROR)
@@ -56,15 +54,16 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
fun log(@CompileTimeConstant msg: String, level: LogLevel) = logBuffer.log(TAG, level, msg)
fun logActiveUnlockTriggered(reason: String?) {
- logBuffer.log("ActiveUnlock", DEBUG,
- { str1 = reason },
- { "initiate active unlock triggerReason=$str1" })
+ logBuffer.log(
+ "ActiveUnlock",
+ DEBUG,
+ { str1 = reason },
+ { "initiate active unlock triggerReason=$str1" }
+ )
}
fun logAuthInterruptDetected(active: Boolean) {
- logBuffer.log(TAG, DEBUG,
- { bool1 = active },
- { "onAuthInterruptDetected($bool1)" })
+ logBuffer.log(TAG, DEBUG, { bool1 = active }, { "onAuthInterruptDetected($bool1)" })
}
fun logBroadcastReceived(action: String?) {
@@ -72,9 +71,12 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logDeviceProvisionedState(deviceProvisioned: Boolean) {
- logBuffer.log(TAG, DEBUG,
- { bool1 = deviceProvisioned },
- { "DEVICE_PROVISIONED state = $bool1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = deviceProvisioned },
+ { "DEVICE_PROVISIONED state = $bool1" }
+ )
}
fun logException(ex: Exception, @CompileTimeConstant logMsg: String) {
@@ -82,46 +84,56 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logFaceAcquired(acquireInfo: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = acquireInfo },
- { "Face acquired acquireInfo=$int1" })
+ logBuffer.log(TAG, DEBUG, { int1 = acquireInfo }, { "Face acquired acquireInfo=$int1" })
}
fun logFaceAuthDisabledForUser(userId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = userId },
- { "Face authentication disabled by DPM for userId: $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = userId },
+ { "Face authentication disabled by DPM for userId: $int1" }
+ )
}
fun logFaceAuthError(msgId: Int, originalErrMsg: String) {
- logBuffer.log(TAG, DEBUG, {
- str1 = originalErrMsg
- int1 = msgId
- }, { "Face error received: $str1 msgId= $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = originalErrMsg
+ int1 = msgId
+ },
+ { "Face error received: $str1 msgId= $int1" }
+ )
}
fun logFaceAuthForWrongUser(authUserId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = authUserId },
- { "Face authenticated for wrong user: $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = authUserId },
+ { "Face authenticated for wrong user: $int1" }
+ )
}
fun logFaceAuthHelpMsg(msgId: Int, helpMsg: String?) {
- logBuffer.log(TAG, DEBUG, {
- int1 = msgId
- str1 = helpMsg
- }, { "Face help received, msgId: $int1 msg: $str1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = msgId
+ str1 = helpMsg
+ },
+ { "Face help received, msgId: $int1 msg: $str1" }
+ )
}
fun logFaceAuthRequested(reason: String?) {
- logBuffer.log(TAG, DEBUG, {
- str1 = reason
- }, { "requestFaceAuth() reason=$str1" })
+ logBuffer.log(TAG, DEBUG, { str1 = reason }, { "requestFaceAuth() reason=$str1" })
}
fun logFaceAuthSuccess(userId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = userId },
- { "Face auth succeeded for user $int1" })
+ logBuffer.log(TAG, DEBUG, { int1 = userId }, { "Face auth succeeded for user $int1" })
}
fun logFaceLockoutReset(@LockoutMode mode: Int) {
@@ -133,21 +145,30 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logFaceUnlockPossible(isFaceUnlockPossible: Boolean) {
- logBuffer.log(TAG, DEBUG,
- { bool1 = isFaceUnlockPossible },
- {"isUnlockWithFacePossible: $bool1"})
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = isFaceUnlockPossible },
+ { "isUnlockWithFacePossible: $bool1" }
+ )
}
fun logFingerprintAuthForWrongUser(authUserId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = authUserId },
- { "Fingerprint authenticated for wrong user: $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = authUserId },
+ { "Fingerprint authenticated for wrong user: $int1" }
+ )
}
fun logFingerprintDisabledForUser(userId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = userId },
- { "Fingerprint disabled by DPM for userId: $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = userId },
+ { "Fingerprint disabled by DPM for userId: $int1" }
+ )
}
fun logFingerprintLockoutReset(@LockoutMode mode: Int) {
@@ -155,42 +176,77 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logFingerprintRunningState(fingerprintRunningState: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = fingerprintRunningState },
- { "fingerprintRunningState: $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = fingerprintRunningState },
+ { "fingerprintRunningState: $int1" }
+ )
}
fun logFingerprintSuccess(userId: Int, isStrongBiometric: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = userId
+ bool1 = isStrongBiometric
+ },
+ { "Fingerprint auth successful: userId: $int1, isStrongBiometric: $bool1" }
+ )
+ }
+
+ fun logFaceDetected(userId: Int, isStrongBiometric: Boolean) {
logBuffer.log(TAG, DEBUG, {
int1 = userId
bool1 = isStrongBiometric
- }, {"Fingerprint auth successful: userId: $int1, isStrongBiometric: $bool1"})
+ }, {"Face detected: userId: $int1, isStrongBiometric: $bool1"})
}
- fun logFingerprintError(msgId: Int, originalErrMsg: String) {
+ fun logFingerprintDetected(userId: Int, isStrongBiometric: Boolean) {
logBuffer.log(TAG, DEBUG, {
- str1 = originalErrMsg
- int1 = msgId
- }, { "Fingerprint error received: $str1 msgId= $int1" })
+ int1 = userId
+ bool1 = isStrongBiometric
+ }, {"Fingerprint detected: userId: $int1, isStrongBiometric: $bool1"})
+ }
+
+ fun logFingerprintError(msgId: Int, originalErrMsg: String) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = originalErrMsg
+ int1 = msgId
+ },
+ { "Fingerprint error received: $str1 msgId= $int1" }
+ )
}
fun logInvalidSubId(subId: Int) {
- logBuffer.log(TAG, INFO,
- { int1 = subId },
- { "Previously active sub id $int1 is now invalid, will remove" })
+ logBuffer.log(
+ TAG,
+ INFO,
+ { int1 = subId },
+ { "Previously active sub id $int1 is now invalid, will remove" }
+ )
}
fun logPrimaryKeyguardBouncerChanged(
- primaryBouncerIsOrWillBeShowing: Boolean,
- primaryBouncerFullyShown: Boolean
+ primaryBouncerIsOrWillBeShowing: Boolean,
+ primaryBouncerFullyShown: Boolean
) {
- logBuffer.log(TAG, DEBUG, {
- bool1 = primaryBouncerIsOrWillBeShowing
- bool2 = primaryBouncerFullyShown
- }, {
- "handlePrimaryBouncerChanged " +
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = primaryBouncerIsOrWillBeShowing
+ bool2 = primaryBouncerFullyShown
+ },
+ {
+ "handlePrimaryBouncerChanged " +
"primaryBouncerIsOrWillBeShowing=$bool1 primaryBouncerFullyShown=$bool2"
- })
+ }
+ )
}
fun logKeyguardListenerModel(model: KeyguardListenModel) {
@@ -198,98 +254,134 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logKeyguardShowingChanged(showing: Boolean, occluded: Boolean, visible: Boolean) {
- logBuffer.log(TAG, DEBUG, {
- bool1 = showing
- bool2 = occluded
- bool3 = visible
- }, {
- "keyguardShowingChanged(showing=$bool1 occluded=$bool2 visible=$bool3)"
- })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = showing
+ bool2 = occluded
+ bool3 = visible
+ },
+ { "keyguardShowingChanged(showing=$bool1 occluded=$bool2 visible=$bool3)" }
+ )
}
fun logMissingSupervisorAppError(userId: Int) {
- logBuffer.log(TAG, ERROR,
- { int1 = userId },
- { "No Profile Owner or Device Owner supervision app found for User $int1" })
+ logBuffer.log(
+ TAG,
+ ERROR,
+ { int1 = userId },
+ { "No Profile Owner or Device Owner supervision app found for User $int1" }
+ )
}
fun logPhoneStateChanged(newState: String?) {
- logBuffer.log(TAG, DEBUG,
- { str1 = newState },
- { "handlePhoneStateChanged($str1)" })
+ logBuffer.log(TAG, DEBUG, { str1 = newState }, { "handlePhoneStateChanged($str1)" })
}
fun logRegisterCallback(callback: KeyguardUpdateMonitorCallback?) {
- logBuffer.log(TAG, VERBOSE,
- { str1 = "$callback" },
- { "*** register callback for $str1" })
+ logBuffer.log(TAG, VERBOSE, { str1 = "$callback" }, { "*** register callback for $str1" })
}
fun logRetryingAfterFaceHwUnavailable(retryCount: Int) {
- logBuffer.log(TAG, WARNING,
- { int1 = retryCount },
- { "Retrying face after HW unavailable, attempt $int1" })
+ logBuffer.log(
+ TAG,
+ WARNING,
+ { int1 = retryCount },
+ { "Retrying face after HW unavailable, attempt $int1" }
+ )
}
fun logRetryAfterFpErrorWithDelay(msgId: Int, errString: String?, delay: Int) {
- logBuffer.log(TAG, DEBUG, {
- int1 = msgId
- int2 = delay
- str1 = "$errString"
- }, {
- "Fingerprint scheduling retry auth after $int2 ms due to($int1) -> $str1"
- })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = msgId
+ int2 = delay
+ str1 = "$errString"
+ },
+ { "Fingerprint scheduling retry auth after $int2 ms due to($int1) -> $str1" }
+ )
}
fun logRetryAfterFpHwUnavailable(retryCount: Int) {
- logBuffer.log(TAG, WARNING,
- { int1 = retryCount },
- { "Retrying fingerprint attempt: $int1" })
+ logBuffer.log(
+ TAG,
+ WARNING,
+ { int1 = retryCount },
+ { "Retrying fingerprint attempt: $int1" }
+ )
}
fun logSendPrimaryBouncerChanged(
primaryBouncerIsOrWillBeShowing: Boolean,
primaryBouncerFullyShown: Boolean,
) {
- logBuffer.log(TAG, DEBUG, {
- bool1 = primaryBouncerIsOrWillBeShowing
- bool2 = primaryBouncerFullyShown
- }, {
- "sendPrimaryBouncerChanged primaryBouncerIsOrWillBeShowing=$bool1 " +
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = primaryBouncerIsOrWillBeShowing
+ bool2 = primaryBouncerFullyShown
+ },
+ {
+ "sendPrimaryBouncerChanged primaryBouncerIsOrWillBeShowing=$bool1 " +
"primaryBouncerFullyShown=$bool2"
- })
+ }
+ )
}
fun logServiceStateChange(subId: Int, serviceState: ServiceState?) {
- logBuffer.log(TAG, DEBUG, {
- int1 = subId
- str1 = "$serviceState"
- }, { "handleServiceStateChange(subId=$int1, serviceState=$str1)" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = subId
+ str1 = "$serviceState"
+ },
+ { "handleServiceStateChange(subId=$int1, serviceState=$str1)" }
+ )
}
fun logServiceStateIntent(action: String?, serviceState: ServiceState?, subId: Int) {
- logBuffer.log(TAG, VERBOSE, {
- str1 = action
- str2 = "$serviceState"
- int1 = subId
- }, { "action $str1 serviceState=$str2 subId=$int1" })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ str1 = action
+ str2 = "$serviceState"
+ int1 = subId
+ },
+ { "action $str1 serviceState=$str2 subId=$int1" }
+ )
}
fun logSimState(subId: Int, slotId: Int, state: Int) {
- logBuffer.log(TAG, DEBUG, {
- int1 = subId
- int2 = slotId
- long1 = state.toLong()
- }, { "handleSimStateChange(subId=$int1, slotId=$int2, state=$long1)" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = subId
+ int2 = slotId
+ long1 = state.toLong()
+ },
+ { "handleSimStateChange(subId=$int1, slotId=$int2, state=$long1)" }
+ )
}
fun logSimStateFromIntent(action: String?, extraSimState: String?, slotId: Int, subId: Int) {
- logBuffer.log(TAG, VERBOSE, {
- str1 = action
- str2 = extraSimState
- int1 = slotId
- int2 = subId
- }, { "action $str1 state: $str2 slotId: $int1 subid: $int2" })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ str1 = action
+ str2 = extraSimState
+ int1 = slotId
+ int2 = subId
+ },
+ { "action $str1 state: $str2 slotId: $int1 subid: $int2" }
+ )
}
fun logSimUnlocked(subId: Int) {
@@ -297,78 +389,98 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logStartedListeningForFace(faceRunningState: Int, faceAuthUiEvent: FaceAuthUiEvent) {
- logBuffer.log(TAG, VERBOSE, {
- int1 = faceRunningState
- str1 = faceAuthUiEvent.reason
- str2 = faceAuthUiEvent.extraInfoToString()
- }, { "startListeningForFace(): $int1, reason: $str1 $str2" })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ int1 = faceRunningState
+ str1 = faceAuthUiEvent.reason
+ str2 = faceAuthUiEvent.extraInfoToString()
+ },
+ { "startListeningForFace(): $int1, reason: $str1 $str2" }
+ )
}
fun logStartedListeningForFaceFromWakeUp(faceRunningState: Int, @WakeReason pmWakeReason: Int) {
- logBuffer.log(TAG, VERBOSE, {
- int1 = faceRunningState
- str1 = PowerManager.wakeReasonToString(pmWakeReason)
- }, { "startListeningForFace(): $int1, reason: wakeUp-$str1" })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ int1 = faceRunningState
+ str1 = PowerManager.wakeReasonToString(pmWakeReason)
+ },
+ { "startListeningForFace(): $int1, reason: wakeUp-$str1" }
+ )
}
fun logStoppedListeningForFace(faceRunningState: Int, faceAuthReason: String) {
- logBuffer.log(TAG, VERBOSE, {
- int1 = faceRunningState
- str1 = faceAuthReason
- }, { "stopListeningForFace(): currentFaceRunningState: $int1, reason: $str1" })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ int1 = faceRunningState
+ str1 = faceAuthReason
+ },
+ { "stopListeningForFace(): currentFaceRunningState: $int1, reason: $str1" }
+ )
}
fun logSubInfo(subInfo: SubscriptionInfo?) {
- logBuffer.log(TAG, VERBOSE,
- { str1 = "$subInfo" },
- { "SubInfo:$str1" })
+ logBuffer.log(TAG, VERBOSE, { str1 = "$subInfo" }, { "SubInfo:$str1" })
}
fun logTimeFormatChanged(newTimeFormat: String?) {
- logBuffer.log(TAG, DEBUG,
- { str1 = newTimeFormat },
- { "handleTimeFormatUpdate timeFormat=$str1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { str1 = newTimeFormat },
+ { "handleTimeFormatUpdate timeFormat=$str1" }
+ )
}
fun logUdfpsPointerDown(sensorId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = sensorId },
- { "onUdfpsPointerDown, sensorId: $int1" })
+ logBuffer.log(TAG, DEBUG, { int1 = sensorId }, { "onUdfpsPointerDown, sensorId: $int1" })
}
fun logUdfpsPointerUp(sensorId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = sensorId },
- { "onUdfpsPointerUp, sensorId: $int1" })
+ logBuffer.log(TAG, DEBUG, { int1 = sensorId }, { "onUdfpsPointerUp, sensorId: $int1" })
}
fun logUnexpectedFaceCancellationSignalState(faceRunningState: Int, unlockPossible: Boolean) {
- logBuffer.log(TAG, ERROR, {
- int1 = faceRunningState
- bool1 = unlockPossible
- }, {
- "Cancellation signal is not null, high chance of bug in " +
- "face auth lifecycle management. " +
- "Face state: $int1, unlockPossible: $bool1"
- })
+ logBuffer.log(
+ TAG,
+ ERROR,
+ {
+ int1 = faceRunningState
+ bool1 = unlockPossible
+ },
+ {
+ "Cancellation signal is not null, high chance of bug in " +
+ "face auth lifecycle management. " +
+ "Face state: $int1, unlockPossible: $bool1"
+ }
+ )
}
fun logUnexpectedFpCancellationSignalState(
fingerprintRunningState: Int,
unlockPossible: Boolean
) {
- logBuffer.log(TAG, ERROR, {
- int1 = fingerprintRunningState
- bool1 = unlockPossible
- }, {
- "Cancellation signal is not null, high chance of bug in " +
- "fp auth lifecycle management. FP state: $int1, unlockPossible: $bool1"
- })
+ logBuffer.log(
+ TAG,
+ ERROR,
+ {
+ int1 = fingerprintRunningState
+ bool1 = unlockPossible
+ },
+ {
+ "Cancellation signal is not null, high chance of bug in " +
+ "fp auth lifecycle management. FP state: $int1, unlockPossible: $bool1"
+ }
+ )
}
fun logUnregisterCallback(callback: KeyguardUpdateMonitorCallback?) {
- logBuffer.log(TAG, VERBOSE,
- { str1 = "$callback" },
- { "*** unregister callback for $str1" })
+ logBuffer.log(TAG, VERBOSE, { str1 = "$callback" }, { "*** unregister callback for $str1" })
}
fun logUserRequestedUnlock(
@@ -376,75 +488,184 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
reason: String?,
dismissKeyguard: Boolean
) {
- logBuffer.log("ActiveUnlock", DEBUG, {
- str1 = requestOrigin?.name
- str2 = reason
- bool1 = dismissKeyguard
- }, { "reportUserRequestedUnlock origin=$str1 reason=$str2 dismissKeyguard=$bool1" })
+ logBuffer.log(
+ "ActiveUnlock",
+ DEBUG,
+ {
+ str1 = requestOrigin?.name
+ str2 = reason
+ bool1 = dismissKeyguard
+ },
+ { "reportUserRequestedUnlock origin=$str1 reason=$str2 dismissKeyguard=$bool1" }
+ )
}
fun logTrustGrantedWithFlags(
- flags: Int,
- newlyUnlocked: Boolean,
- userId: Int,
- message: String?
+ flags: Int,
+ newlyUnlocked: Boolean,
+ userId: Int,
+ message: String?
) {
- logBuffer.log(TAG, DEBUG, {
- int1 = flags
- bool1 = newlyUnlocked
- int2 = userId
- str1 = message
- }, { "trustGrantedWithFlags[user=$int2] newlyUnlocked=$bool1 " +
- "flags=${TrustGrantFlags(int1)} message=$str1" })
- }
-
- fun logTrustChanged(
- wasTrusted: Boolean,
- isNowTrusted: Boolean,
- userId: Int
- ) {
- logBuffer.log(TAG, DEBUG, {
- bool1 = wasTrusted
- bool2 = isNowTrusted
- int1 = userId
- }, { "onTrustChanged[user=$int1] wasTrusted=$bool1 isNowTrusted=$bool2" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = flags
+ bool1 = newlyUnlocked
+ int2 = userId
+ str1 = message
+ },
+ {
+ "trustGrantedWithFlags[user=$int2] newlyUnlocked=$bool1 " +
+ "flags=${TrustGrantFlags(int1)} message=$str1"
+ }
+ )
+ }
+
+ fun logTrustChanged(wasTrusted: Boolean, isNowTrusted: Boolean, userId: Int) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = wasTrusted
+ bool2 = isNowTrusted
+ int1 = userId
+ },
+ { "onTrustChanged[user=$int1] wasTrusted=$bool1 isNowTrusted=$bool2" }
+ )
}
fun logKeyguardStateUpdate(
- secure: Boolean,
- canDismissLockScreen: Boolean,
- trusted: Boolean,
- trustManaged: Boolean
-
+ secure: Boolean,
+ canDismissLockScreen: Boolean,
+ trusted: Boolean,
+ trustManaged: Boolean
) {
- logBuffer.log("KeyguardState", DEBUG, {
- bool1 = secure
- bool2 = canDismissLockScreen
- bool3 = trusted
- bool4 = trustManaged
- }, { "#update secure=$bool1 canDismissKeyguard=$bool2" +
- " trusted=$bool3 trustManaged=$bool4" })
+ logBuffer.log(
+ "KeyguardState",
+ DEBUG,
+ {
+ bool1 = secure
+ bool2 = canDismissLockScreen
+ bool3 = trusted
+ bool4 = trustManaged
+ },
+ {
+ "#update secure=$bool1 canDismissKeyguard=$bool2" +
+ " trusted=$bool3 trustManaged=$bool4"
+ }
+ )
}
fun logSkipUpdateFaceListeningOnWakeup(@WakeReason pmWakeReason: Int) {
- logBuffer.log(TAG, VERBOSE, {
- str1 = PowerManager.wakeReasonToString(pmWakeReason)
- }, { "Skip updating face listening state on wakeup from $str1"})
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ { str1 = PowerManager.wakeReasonToString(pmWakeReason) },
+ { "Skip updating face listening state on wakeup from $str1" }
+ )
}
fun logTaskStackChangedForAssistant(assistantVisible: Boolean) {
- logBuffer.log(TAG, VERBOSE, {
- bool1 = assistantVisible
- }, {
- "TaskStackChanged for ACTIVITY_TYPE_ASSISTANT, assistant visible: $bool1"
- })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ { bool1 = assistantVisible },
+ { "TaskStackChanged for ACTIVITY_TYPE_ASSISTANT, assistant visible: $bool1" }
+ )
}
fun logAssistantVisible(assistantVisible: Boolean) {
- logBuffer.log(TAG, VERBOSE, {
- bool1 = assistantVisible
- }, {
- "Updating mAssistantVisible to new value: $bool1"
- })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ { bool1 = assistantVisible },
+ { "Updating mAssistantVisible to new value: $bool1" }
+ )
+ }
+
+ fun logReportSuccessfulBiometricUnlock(isStrongBiometric: Boolean, userId: Int) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = isStrongBiometric
+ int1 = userId
+ },
+ { "reporting successful biometric unlock: isStrongBiometric: $bool1, userId: $int1" }
+ )
+ }
+
+ fun logHandlerHasAuthContinueMsgs(action: Int) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = action },
+ {
+ "MSG_BIOMETRIC_AUTHENTICATION_CONTINUE already queued up, " +
+ "ignoring updating FP listening state to $int1"
+ }
+ )
+ }
+
+ fun logFaceEnrolledUpdated(oldValue: Boolean, newValue: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = oldValue
+ bool2 = newValue
+ },
+ { "Face enrolled state changed: old: $bool1, new: $bool2" }
+ )
+ }
+
+ fun logFpEnrolledUpdated(userId: Int, oldValue: Boolean, newValue: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = userId
+ bool1 = oldValue
+ bool2 = newValue
+ },
+ { "Fp enrolled state changed for userId: $int1 old: $bool1, new: $bool2" }
+ )
+ }
+
+ fun logTrustUsuallyManagedUpdated(
+ userId: Int,
+ oldValue: Boolean,
+ newValue: Boolean,
+ context: String
+ ) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = userId
+ bool1 = oldValue
+ bool2 = newValue
+ str1 = context
+ },
+ {
+ "trustUsuallyManaged changed for " +
+ "userId: $int1 " +
+ "old: $bool1, " +
+ "new: $bool2 " +
+ "context: $context"
+ }
+ )
+ }
+
+ fun logHandleBatteryUpdate(isInteresting: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = isInteresting
+ },
+ { "handleBatteryUpdate: $bool1" }
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt b/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
index 0f00a040b094..603471b1de41 100644
--- a/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
+++ b/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
@@ -73,6 +73,10 @@ class ScreenOnCoordinator @Inject constructor(
@BinderThread
fun onScreenTurnedOn() {
foldAodAnimationController?.onScreenTurnedOn()
+ }
+
+ @BinderThread
+ fun onScreenTurnedOff() {
pendingTasks.reset()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 03d999f697d0..0002ae95f476 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -24,6 +24,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -37,7 +38,6 @@ import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
-import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -195,7 +195,13 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
return false;
}
- void onBatteryLevelChanged(int level, boolean pluggedIn) {
+ /**
+ * Update battery level
+ *
+ * @param level int between 0 and 100 (representing percentage value)
+ * @param pluggedIn whether the device is plugged in or not
+ */
+ public void onBatteryLevelChanged(@IntRange(from = 0, to = 100) int level, boolean pluggedIn) {
mDrawable.setCharging(pluggedIn);
mDrawable.setBatteryLevel(level);
mCharging = pluggedIn;
@@ -340,10 +346,9 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
}
if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
updatePercentText();
- addView(mBatteryPercentView,
- new ViewGroup.LayoutParams(
- LayoutParams.WRAP_CONTENT,
- LayoutParams.MATCH_PARENT));
+ addView(mBatteryPercentView, new LayoutParams(
+ LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT));
}
} else {
if (showing) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
index 3ea3cd171062..52312b8e8add 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
@@ -97,7 +97,6 @@ open class AuthBiometricFingerprintIconController(
val iconContentDescription = getIconContentDescription(newState)
if (iconContentDescription != null) {
iconView.contentDescription = iconContentDescription
- iconViewOverlay.contentDescription = iconContentDescription
}
iconView.frame = 0
@@ -152,7 +151,7 @@ open class AuthBiometricFingerprintIconController(
STATE_AUTHENTICATING_ANIMATING_IN,
STATE_AUTHENTICATING,
STATE_PENDING_CONFIRMATION,
- STATE_AUTHENTICATED -> R.string.accessibility_fingerprint_dialog_fingerprint_icon
+ STATE_AUTHENTICATED -> R.string.security_settings_sfps_enroll_find_sensor_message
STATE_ERROR,
STATE_HELP -> R.string.biometric_dialog_try_again
else -> null
@@ -231,21 +230,29 @@ open class AuthBiometricFingerprintIconController(
if (isReverseDefaultRotation) (rotation + 1) % 4 else rotation
@RawRes
- private fun getSideFpsAnimationForTransition(rotation: Int): Int = when (rotation) {
- Surface.ROTATION_90 -> if (isDeviceFolded) {
- R.raw.biometricprompt_folded_base_topleft
- } else {
- R.raw.biometricprompt_portrait_base_topleft
- }
- Surface.ROTATION_270 -> if (isDeviceFolded) {
- R.raw.biometricprompt_folded_base_bottomright
- } else {
- R.raw.biometricprompt_portrait_base_bottomright
- }
- else -> if (isDeviceFolded) {
- R.raw.biometricprompt_folded_base_default
- } else {
- R.raw.biometricprompt_landscape_base
+ private fun getSideFpsAnimationForTransition(rotation: Int): Int {
+ when (rotation) {
+ Surface.ROTATION_90 -> if (context.isInRearDisplayMode()) {
+ return R.raw.biometricprompt_rear_portrait_reverse_base
+ } else if (isDeviceFolded) {
+ return R.raw.biometricprompt_folded_base_topleft
+ } else {
+ return R.raw.biometricprompt_portrait_base_topleft
+ }
+ Surface.ROTATION_270 -> if (context.isInRearDisplayMode()) {
+ return R.raw.biometricprompt_rear_portrait_base
+ } else if (isDeviceFolded) {
+ return R.raw.biometricprompt_folded_base_bottomright
+ } else {
+ return R.raw.biometricprompt_portrait_base_bottomright
+ }
+ else -> if (context.isInRearDisplayMode()) {
+ return R.raw.biometricprompt_rear_landscape_base
+ } else if (isDeviceFolded) {
+ return R.raw.biometricprompt_folded_base_default
+ } else {
+ return R.raw.biometricprompt_landscape_base
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index e12c1706798e..a7b6e6ae6d40 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -658,6 +658,7 @@ public abstract class AuthBiometricView extends LinearLayout {
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mIconController.onConfigurationChanged(newConfig);
+ updateState(mSavedState.getInt(AuthDialog.KEY_BIOMETRIC_STATE));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index febf75e90a14..68e1f72d042a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -847,7 +847,7 @@ public class AuthContainerView extends LinearLayout
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
windowFlags,
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index d68fcd0a5922..541f69c62a1f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -26,6 +26,7 @@ import android.hardware.biometrics.BiometricSourceType
import androidx.annotation.VisibleForTesting
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.keyguard.logging.KeyguardLogger
import com.android.settingslib.Utils
import com.android.systemui.R
import com.android.systemui.animation.Interpolators
@@ -40,8 +41,8 @@ import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.BiometricUnlockController
+import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_DISMISS_BOUNCER
import com.android.systemui.statusbar.phone.CentralSurfaces
-import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -59,7 +60,9 @@ import javax.inject.Provider
* The ripple uses the accent color of the current theme.
*/
@CentralSurfacesScope
-class AuthRippleController @Inject constructor(
+class AuthRippleController
+@Inject
+constructor(
private val centralSurfaces: CentralSurfaces,
private val sysuiContext: Context,
private val authController: AuthController,
@@ -69,17 +72,18 @@ class AuthRippleController @Inject constructor(
private val wakefulnessLifecycle: WakefulnessLifecycle,
private val commandRegistry: CommandRegistry,
private val notificationShadeWindowController: NotificationShadeWindowController,
- private val bypassController: KeyguardBypassController,
private val biometricUnlockController: BiometricUnlockController,
private val udfpsControllerProvider: Provider<UdfpsController>,
private val statusBarStateController: StatusBarStateController,
private val featureFlags: FeatureFlags,
- rippleView: AuthRippleView?
-) : ViewController<AuthRippleView>(rippleView), KeyguardStateController.Callback,
+ private val logger: KeyguardLogger,
+ rippleView: AuthRippleView?
+) :
+ ViewController<AuthRippleView>(rippleView),
+ KeyguardStateController.Callback,
WakefulnessLifecycle.Observer {
- @VisibleForTesting
- internal var startLightRevealScrimOnKeyguardFadingAway = false
+ @VisibleForTesting internal var startLightRevealScrimOnKeyguardFadingAway = false
var lightRevealScrimAnimator: ValueAnimator? = null
var fingerprintSensorLocation: Point? = null
private var faceSensorLocation: Point? = null
@@ -88,6 +92,16 @@ class AuthRippleController @Inject constructor(
private var udfpsController: UdfpsController? = null
private var udfpsRadius: Float = -1f
+ private val biometricModeListener = object : BiometricUnlockController.BiometricModeListener {
+ override fun onModeChanged(mode: Int) {
+ // isBiometricUnlock does not cover the scenario when biometrics unlocks
+ // the device while the bouncer is showing.
+ if (biometricUnlockController.isBiometricUnlock || mode == MODE_DISMISS_BOUNCER) {
+ showUnlockRipple(biometricUnlockController.biometricType)
+ }
+ }
+ }
+
override fun onInit() {
mView.setAlphaInDuration(sysuiContext.resources.getInteger(
R.integer.auth_ripple_alpha_in_duration).toLong())
@@ -104,6 +118,7 @@ class AuthRippleController @Inject constructor(
keyguardStateController.addCallback(this)
wakefulnessLifecycle.addObserver(this)
commandRegistry.registerCommand("auth-ripple") { AuthRippleCommand() }
+ biometricUnlockController.addBiometricModeListener(biometricModeListener)
}
@VisibleForTesting
@@ -115,13 +130,17 @@ class AuthRippleController @Inject constructor(
keyguardStateController.removeCallback(this)
wakefulnessLifecycle.removeObserver(this)
commandRegistry.unregisterCommand("auth-ripple")
+ biometricUnlockController.removeBiometricModeListener(biometricModeListener)
notificationShadeWindowController.setForcePluginOpen(false, this)
}
fun showUnlockRipple(biometricSourceType: BiometricSourceType) {
- if (!keyguardStateController.isShowing ||
- !keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(biometricSourceType)) {
+ val keyguardNotShowing = !keyguardStateController.isShowing
+ val unlockNotAllowed = !keyguardUpdateMonitor
+ .isUnlockingWithBiometricAllowed(biometricSourceType)
+ if (keyguardNotShowing || unlockNotAllowed) {
+ logger.notShowingUnlockRipple(keyguardNotShowing, unlockNotAllowed)
return
}
@@ -138,13 +157,11 @@ class AuthRippleController @Inject constructor(
Math.max(it.y, centralSurfaces.displayHeight.toInt() - it.y)
)
)
+ logger.showingUnlockRippleAt(it.x, it.y, "FP sensor radius: $udfpsRadius")
showUnlockedRipple()
}
} else if (biometricSourceType == BiometricSourceType.FACE) {
- if (!bypassController.canBypass() && !authController.isUdfpsFingerDown) {
- return
- }
- faceSensorLocation?.let {
+ faceSensorLocation?.let {
mView.setSensorLocation(it)
circleReveal = CircleReveal(
it.x,
@@ -155,6 +172,7 @@ class AuthRippleController @Inject constructor(
Math.max(it.y, centralSurfaces.displayHeight.toInt() - it.y)
)
)
+ logger.showingUnlockRippleAt(it.x, it.y, "Face unlock ripple")
showUnlockedRipple()
}
}
@@ -264,7 +282,6 @@ class AuthRippleController @Inject constructor(
if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
mView.fadeDwellRipple()
}
- showUnlockRipple(biometricSourceType)
}
override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType) {
@@ -390,6 +407,7 @@ class AuthRippleController @Inject constructor(
}
companion object {
- const val RIPPLE_ANIMATION_DURATION: Long = 1533
+ const val RIPPLE_ANIMATION_DURATION: Long = 800
+ const val TAG = "AuthRippleController"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 58b230f52e93..84094626193d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -31,7 +31,7 @@ import com.android.internal.graphics.ColorUtils
import com.android.systemui.animation.Interpolators
import com.android.systemui.surfaceeffects.ripple.RippleShader
-private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
+private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
/**
* Handles two ripple effects: dwell ripple and unlocked ripple
@@ -75,8 +75,8 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
}
private var radius: Float = 0f
set(value) {
- rippleShader.setMaxSize(value * 2f, value * 2f)
- field = value
+ field = value * .9f
+ rippleShader.rippleSize.setMaxSize(field * 2f, field * 2f)
}
private var origin: Point = Point()
set(value) {
@@ -87,8 +87,9 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
init {
rippleShader.color = 0xffffffff.toInt() // default color
rippleShader.rawProgress = 0f
+ rippleShader.pixelDensity = resources.displayMetrics.density
rippleShader.sparkleStrength = RIPPLE_SPARKLE_STRENGTH
- setupRippleFadeParams()
+ updateRippleFadeParams()
ripplePaint.shader = rippleShader
dwellShader.color = 0xffffffff.toInt() // default color
@@ -266,7 +267,6 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
unlockedRippleAnimator?.cancel()
val rippleAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
- interpolator = Interpolators.LINEAR_OUT_SLOW_IN
duration = AuthRippleController.RIPPLE_ANIMATION_DURATION
addUpdateListener { animator ->
val now = animator.currentPlayTime
@@ -277,7 +277,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
}
}
- val alphaInAnimator = ValueAnimator.ofInt(0, 255).apply {
+ val alphaInAnimator = ValueAnimator.ofInt(0, 62).apply {
duration = alphaInDuration
addUpdateListener { animator ->
rippleShader.color = ColorUtils.setAlphaComponent(
@@ -339,15 +339,17 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
)
}
- private fun setupRippleFadeParams() {
+ private fun updateRippleFadeParams() {
with(rippleShader) {
- baseRingFadeParams.fadeOutStart = RippleShader.DEFAULT_BASE_RING_FADE_OUT_START
- baseRingFadeParams.fadeOutEnd = RippleShader.DEFAULT_FADE_OUT_END
-
- centerFillFadeParams.fadeInStart = RippleShader.DEFAULT_FADE_IN_START
- centerFillFadeParams.fadeInEnd = RippleShader.DEFAULT_CENTER_FILL_FADE_IN_END
- centerFillFadeParams.fadeOutStart = RippleShader.DEFAULT_CENTER_FILL_FADE_OUT_START
- centerFillFadeParams.fadeOutEnd = RippleShader.DEFAULT_CENTER_FILL_FADE_OUT_END
+ baseRingFadeParams.fadeInStart = 0f
+ baseRingFadeParams.fadeInEnd = .2f
+ baseRingFadeParams.fadeOutStart = .2f
+ baseRingFadeParams.fadeOutEnd = 1f
+
+ centerFillFadeParams.fadeInStart = 0f
+ centerFillFadeParams.fadeInEnd = .15f
+ centerFillFadeParams.fadeOutStart = .15f
+ centerFillFadeParams.fadeOutEnd = .56f
}
}
@@ -364,7 +366,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
if (drawRipple) {
canvas?.drawCircle(origin.x.toFloat(), origin.y.toFloat(),
- rippleShader.currentWidth, ripplePaint)
+ rippleShader.rippleSize.currentWidth, ripplePaint)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
index fabc1c1bb908..e16121d1104e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
@@ -49,8 +49,8 @@ constructor(
/**
* @property messagesToDefer messages that shouldn't show immediately when received, but may be
- * shown later if the message is the most frequent acquiredInfo processed and meets [threshold]
- * percentage of all passed acquired frames.
+ * shown later if the message is the most frequent acquiredInfo processed and meets [threshold]
+ * percentage of all passed acquired frames.
*/
open class BiometricMessageDeferral(
private val messagesToDefer: Set<Int>,
@@ -127,8 +127,9 @@ open class BiometricMessageDeferral(
/**
* Get the most frequent deferred message that meets the [threshold] percentage of processed
* frames.
+ *
* @return null if no acquiredInfo have been deferred OR deferred messages didn't meet the
- * [threshold] percentage.
+ * [threshold] percentage.
*/
fun getDeferredMessage(): CharSequence? {
mostFrequentAcquiredInfoToDefer?.let {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index 6c490780b79a..b62c729f1c19 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -64,6 +64,7 @@ import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.recents.OverviewProxyService
import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.traceSection
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -172,12 +173,16 @@ constructor(
override fun show(
sensorId: Int,
@BiometricOverlayConstants.ShowReason reason: Int
- ) =
- if (reason.isReasonToAutoShow(activityTaskManager)) {
+ ) {
+ if (
+ reason.isReasonToAutoShow(activityTaskManager) &&
+ !context.isInRearDisplayMode()
+ ) {
show(SideFpsUiRequestSource.AUTO_SHOW, reason)
} else {
hide(SideFpsUiRequestSource.AUTO_SHOW)
}
+ }
override fun hide(sensorId: Int) = hide(SideFpsUiRequestSource.AUTO_SHOW)
}
@@ -211,7 +216,9 @@ constructor(
requests.add(request)
mainExecutor.execute {
if (overlayView == null) {
- createOverlayForDisplay(reason)
+ traceSection("SideFpsController#show(request=${request.name}, reason=$reason") {
+ createOverlayForDisplay(reason)
+ }
} else {
Log.v(TAG, "overlay already shown")
}
@@ -223,7 +230,7 @@ constructor(
requests.remove(request)
mainExecutor.execute {
if (requests.isEmpty()) {
- overlayView = null
+ traceSection("SideFpsController#hide(${request.name}") { overlayView = null }
}
}
}
@@ -488,7 +495,9 @@ class OrientationReasonListener(
displayManager,
handler,
BiometricDisplayListener.SensorType.SideFingerprint(sensorProps)
- ) { onOrientationChanged(reason) }
+ ) {
+ onOrientationChanged(reason)
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
index addbee954fea..71cb35f3041c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
@@ -347,6 +347,7 @@ constructor(
/**
* Overrides non-bouncer show logic in shouldPauseAuth to still show icon.
+ *
* @return whether the udfpsBouncer has been newly shown or hidden
*/
private fun showUdfpsBouncer(show: Boolean): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
index d0d6f4cbf166..3d563267ca74 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
@@ -36,6 +36,7 @@ import android.view.WindowManager
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityManager
import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.R
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
@@ -117,4 +118,7 @@ object Utils {
@Retention(RetentionPolicy.SOURCE)
@IntDef(CREDENTIAL_PIN, CREDENTIAL_PATTERN, CREDENTIAL_PASSWORD)
internal annotation class CredentialType
-} \ No newline at end of file
+}
+
+fun Context.isInRearDisplayMode(): Boolean = resources.getIntArray(
+ com.android.internal.R.array.config_rearDisplayDeviceStates).isNotEmpty() \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java
index 8e062bd69d63..653c12ef955e 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java
@@ -46,11 +46,11 @@ public class BroadcastDialog extends SystemUIDialog {
@VisibleForTesting
protected View mDialogView;
private MediaOutputDialogFactory mMediaOutputDialogFactory;
- private String mSwitchBroadcastApp;
+ private String mCurrentBroadcastApp;
private String mOutputPackageName;
public BroadcastDialog(Context context, MediaOutputDialogFactory mediaOutputDialogFactory,
- String switchBroadcastApp, String outputPkgName, UiEventLogger uiEventLogger) {
+ String currentBroadcastApp, String outputPkgName, UiEventLogger uiEventLogger) {
super(context);
if (DEBUG) {
Log.d(TAG, "Init BroadcastDialog");
@@ -58,7 +58,7 @@ public class BroadcastDialog extends SystemUIDialog {
mContext = getContext();
mMediaOutputDialogFactory = mediaOutputDialogFactory;
- mSwitchBroadcastApp = switchBroadcastApp;
+ mCurrentBroadcastApp = currentBroadcastApp;
mOutputPackageName = outputPkgName;
mUiEventLogger = uiEventLogger;
}
@@ -77,20 +77,18 @@ public class BroadcastDialog extends SystemUIDialog {
TextView title = mDialogView.requireViewById(R.id.dialog_title);
TextView subTitle = mDialogView.requireViewById(R.id.dialog_subtitle);
- title.setText(
- mContext.getString(R.string.bt_le_audio_broadcast_dialog_title,
- MediaDataUtils.getAppLabel(mContext, mOutputPackageName,
- mContext.getString(
- R.string.bt_le_audio_broadcast_dialog_unknown_name))));
- subTitle.setText(
- mContext.getString(R.string.bt_le_audio_broadcast_dialog_sub_title,
- mSwitchBroadcastApp));
+ title.setText(mContext.getString(
+ R.string.bt_le_audio_broadcast_dialog_title, mCurrentBroadcastApp));
+ String switchBroadcastApp = MediaDataUtils.getAppLabel(mContext, mOutputPackageName,
+ mContext.getString(R.string.bt_le_audio_broadcast_dialog_unknown_name));
+ subTitle.setText(mContext.getString(
+ R.string.bt_le_audio_broadcast_dialog_sub_title, switchBroadcastApp));
Button switchBroadcast = mDialogView.requireViewById(R.id.switch_broadcast);
Button changeOutput = mDialogView.requireViewById(R.id.change_output);
Button cancelBtn = mDialogView.requireViewById(R.id.cancel);
switchBroadcast.setText(mContext.getString(
- R.string.bt_le_audio_broadcast_dialog_switch_app, mSwitchBroadcastApp), null);
+ R.string.bt_le_audio_broadcast_dialog_switch_app, switchBroadcastApp));
changeOutput.setOnClickListener((view) -> {
mMediaOutputDialogFactory.create(mOutputPackageName, true, null);
dismiss();
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
index 8a54345ae28c..1b699e8ea5dd 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
@@ -47,10 +47,15 @@ public class BroadcastDialogController {
mMediaOutputDialogFactory = mediaOutputDialogFactory;
}
- public void createBroadcastDialog(String switchAppName, String outputPkgName,
+ /** Creates a [BroadcastDialog] for the user to switch broadcast or change the output device
+ *
+ * @param currentBroadcastAppName Indicates the APP name currently broadcasting
+ * @param outputPkgName Indicates the output media package name to be switched
+ */
+ public void createBroadcastDialog(String currentBroadcastAppName, String outputPkgName,
boolean aboveStatusBar, View view) {
BroadcastDialog broadcastDialog = new BroadcastDialog(mContext, mMediaOutputDialogFactory,
- switchAppName, outputPkgName, mUiEventLogger);
+ currentBroadcastAppName, outputPkgName, mUiEventLogger);
if (view != null) {
mDialogLaunchAnimator.showFromView(broadcastDialog, view);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index 36103f8db8d8..f6217f16d054 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -33,7 +33,9 @@ import android.widget.TextView;
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
+import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.surfaceeffects.ripple.RippleAnimationConfig;
+import com.android.systemui.surfaceeffects.ripple.RippleShader;
import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape;
import com.android.systemui.surfaceeffects.ripple.RippleView;
@@ -44,10 +46,12 @@ import java.text.NumberFormat;
*/
final class WirelessChargingLayout extends FrameLayout {
private static final long CIRCLE_RIPPLE_ANIMATION_DURATION = 1500;
- private static final long ROUNDED_BOX_RIPPLE_ANIMATION_DURATION = 1750;
+ private static final long ROUNDED_BOX_RIPPLE_ANIMATION_DURATION = 3000;
private static final int SCRIM_COLOR = 0x4C000000;
private static final int SCRIM_FADE_DURATION = 300;
private RippleView mRippleView;
+ // This is only relevant to the rounded box ripple.
+ private RippleShader.SizeAtProgress[] mSizeAtProgressArray;
WirelessChargingLayout(Context context, int transmittingBatteryLevel, int batteryLevel,
boolean isDozing, RippleShape rippleShape) {
@@ -125,20 +129,23 @@ final class WirelessChargingLayout extends FrameLayout {
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator);
- ValueAnimator scrimFadeInAnimator = ObjectAnimator.ofArgb(this,
- "backgroundColor", Color.TRANSPARENT, SCRIM_COLOR);
- scrimFadeInAnimator.setDuration(SCRIM_FADE_DURATION);
- scrimFadeInAnimator.setInterpolator(Interpolators.LINEAR);
- ValueAnimator scrimFadeOutAnimator = ObjectAnimator.ofArgb(this,
- "backgroundColor", SCRIM_COLOR, Color.TRANSPARENT);
- scrimFadeOutAnimator.setDuration(SCRIM_FADE_DURATION);
- scrimFadeOutAnimator.setInterpolator(Interpolators.LINEAR);
- scrimFadeOutAnimator.setStartDelay((rippleShape == RippleShape.CIRCLE
- ? CIRCLE_RIPPLE_ANIMATION_DURATION : ROUNDED_BOX_RIPPLE_ANIMATION_DURATION)
- - SCRIM_FADE_DURATION);
- AnimatorSet animatorSetScrim = new AnimatorSet();
- animatorSetScrim.playTogether(scrimFadeInAnimator, scrimFadeOutAnimator);
- animatorSetScrim.start();
+ // For large screens docking animation, we don't play the background scrim.
+ if (!Utilities.isLargeScreen(context)) {
+ ValueAnimator scrimFadeInAnimator = ObjectAnimator.ofArgb(this,
+ "backgroundColor", Color.TRANSPARENT, SCRIM_COLOR);
+ scrimFadeInAnimator.setDuration(SCRIM_FADE_DURATION);
+ scrimFadeInAnimator.setInterpolator(Interpolators.LINEAR);
+ ValueAnimator scrimFadeOutAnimator = ObjectAnimator.ofArgb(this,
+ "backgroundColor", SCRIM_COLOR, Color.TRANSPARENT);
+ scrimFadeOutAnimator.setDuration(SCRIM_FADE_DURATION);
+ scrimFadeOutAnimator.setInterpolator(Interpolators.LINEAR);
+ scrimFadeOutAnimator.setStartDelay((rippleShape == RippleShape.CIRCLE
+ ? CIRCLE_RIPPLE_ANIMATION_DURATION : ROUNDED_BOX_RIPPLE_ANIMATION_DURATION)
+ - SCRIM_FADE_DURATION);
+ AnimatorSet animatorSetScrim = new AnimatorSet();
+ animatorSetScrim.playTogether(scrimFadeInAnimator, scrimFadeOutAnimator);
+ animatorSetScrim.start();
+ }
mRippleView = findViewById(R.id.wireless_charging_ripple);
mRippleView.setupShader(rippleShape);
@@ -147,7 +154,26 @@ final class WirelessChargingLayout extends FrameLayout {
if (mRippleView.getRippleShape() == RippleShape.ROUNDED_BOX) {
mRippleView.setDuration(ROUNDED_BOX_RIPPLE_ANIMATION_DURATION);
mRippleView.setSparkleStrength(0.22f);
- mRippleView.setColor(color, 28);
+ mRippleView.setColor(color, 102); // 40% of opacity.
+ mRippleView.setBaseRingFadeParams(
+ /* fadeInStart = */ 0f,
+ /* fadeInEnd = */ 0f,
+ /* fadeOutStart = */ 0.2f,
+ /* fadeOutEnd= */ 0.47f
+ );
+ mRippleView.setSparkleRingFadeParams(
+ /* fadeInStart = */ 0f,
+ /* fadeInEnd = */ 0f,
+ /* fadeOutStart = */ 0.2f,
+ /* fadeOutEnd= */ 1f
+ );
+ mRippleView.setCenterFillFadeParams(
+ /* fadeInStart = */ 0f,
+ /* fadeInEnd = */ 0f,
+ /* fadeOutStart = */ 0f,
+ /* fadeOutEnd= */ 0.2f
+ );
+ mRippleView.setBlur(6.5f, 2.5f);
} else {
mRippleView.setDuration(CIRCLE_RIPPLE_ANIMATION_DURATION);
mRippleView.setColor(color, RippleAnimationConfig.RIPPLE_DEFAULT_ALPHA);
@@ -246,9 +272,7 @@ final class WirelessChargingLayout extends FrameLayout {
int height = getMeasuredHeight();
mRippleView.setCenter(width * 0.5f, height * 0.5f);
if (mRippleView.getRippleShape() == RippleShape.ROUNDED_BOX) {
- // Those magic numbers are introduced for visual polish. This aspect ratio maps with
- // the tablet's docking station.
- mRippleView.setMaxSize(width * 1.36f, height * 1.46f);
+ updateRippleSizeAtProgressList(width, height);
} else {
float maxSize = Math.max(width, height);
mRippleView.setMaxSize(maxSize, maxSize);
@@ -257,4 +281,36 @@ final class WirelessChargingLayout extends FrameLayout {
super.onLayout(changed, left, top, right, bottom);
}
+
+ private void updateRippleSizeAtProgressList(float width, float height) {
+ if (mSizeAtProgressArray == null) {
+ float maxSize = Math.max(width, height);
+ mSizeAtProgressArray = new RippleShader.SizeAtProgress[] {
+ // Those magic numbers are introduced for visual polish. It starts from a pill
+ // shape and expand to a full circle.
+ new RippleShader.SizeAtProgress(0f, 0f, 0f),
+ new RippleShader.SizeAtProgress(0.3f, width * 0.4f, height * 0.4f),
+ new RippleShader.SizeAtProgress(1f, maxSize, maxSize)
+ };
+ } else {
+ // Same multipliers, just need to recompute with the new width and height.
+ RippleShader.SizeAtProgress first = mSizeAtProgressArray[0];
+ first.setT(0f);
+ first.setWidth(0f);
+ first.setHeight(0f);
+
+ RippleShader.SizeAtProgress second = mSizeAtProgressArray[1];
+ second.setT(0.3f);
+ second.setWidth(width * 0.4f);
+ second.setHeight(height * 0.4f);
+
+ float maxSize = Math.max(width, height);
+ RippleShader.SizeAtProgress last = mSizeAtProgressArray[2];
+ last.setT(1f);
+ last.setWidth(maxSize);
+ last.setHeight(maxSize);
+ }
+
+ mRippleView.setSizeAtProgresses(mSizeAtProgressArray);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index e9ac840cf4f4..f6b71336675f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -402,7 +402,7 @@ public class BrightLineFalsingManager implements FalsingManager {
|| mAccessibilityManager.isTouchExplorationEnabled()
|| mDataProvider.isA11yAction()
|| (mFeatureFlags.isEnabled(Flags.FALSING_OFF_FOR_UNFOLDED)
- && !mDataProvider.isFolded());
+ && mDataProvider.isUnfolded());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
index 5f347c158818..f83885b7bb32 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
@@ -38,6 +38,7 @@ import javax.inject.Inject;
public class FalsingDataProvider {
private static final long MOTION_EVENT_AGE_MS = 1000;
+ private static final long DROP_EVENT_THRESHOLD_MS = 50;
private static final float THREE_HUNDRED_SIXTY_DEG = (float) (2 * Math.PI);
private final int mWidthPixels;
@@ -60,6 +61,7 @@ public class FalsingDataProvider {
private float mAngle = 0;
private MotionEvent mFirstRecentMotionEvent;
private MotionEvent mLastMotionEvent;
+ private boolean mDropLastEvent;
private boolean mJustUnlockedWithFace;
private boolean mA11YAction;
@@ -95,6 +97,12 @@ public class FalsingDataProvider {
// Ensure prior gesture was completed. May be a no-op.
completePriorGesture();
}
+
+ // Drop the gesture closing event if it is close in time to a previous ACTION_MOVE event.
+ // The reason is that the closing ACTION_UP event of a swipe can be a bit offseted from the
+ // previous ACTION_MOVE event and when it happens, it makes some classifiers fail.
+ mDropLastEvent = shouldDropEvent(motionEvent);
+
mRecentMotionEvents.addAll(motionEvents);
FalsingClassifier.logVerbose("Size: " + mRecentMotionEvents.size());
@@ -129,6 +137,7 @@ public class FalsingDataProvider {
mPriorMotionEvents = mRecentMotionEvents;
mRecentMotionEvents = new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS);
}
+ mDropLastEvent = false;
mA11YAction = false;
}
@@ -150,8 +159,18 @@ public class FalsingDataProvider {
return mYdpi;
}
+ /**
+ * Get the {@link MotionEvent}s of the most recent gesture.
+ *
+ * Note that this list may not include the last recorded event.
+ * @see #mDropLastEvent
+ */
public List<MotionEvent> getRecentMotionEvents() {
- return mRecentMotionEvents;
+ if (!mDropLastEvent || mRecentMotionEvents.isEmpty()) {
+ return mRecentMotionEvents;
+ } else {
+ return mRecentMotionEvents.subList(0, mRecentMotionEvents.size() - 1);
+ }
}
public List<MotionEvent> getPriorMotionEvents() {
@@ -169,7 +188,12 @@ public class FalsingDataProvider {
return mFirstRecentMotionEvent;
}
- /** Get the last recorded {@link MotionEvent}. */
+ /**
+ * Get the last {@link MotionEvent} of the most recent gesture.
+ *
+ * Note that this may be the event prior to the last recorded event.
+ * @see #mDropLastEvent
+ */
public MotionEvent getLastMotionEvent() {
recalculateData();
return mLastMotionEvent;
@@ -236,12 +260,13 @@ public class FalsingDataProvider {
return;
}
- if (mRecentMotionEvents.isEmpty()) {
+ List<MotionEvent> recentMotionEvents = getRecentMotionEvents();
+ if (recentMotionEvents.isEmpty()) {
mFirstRecentMotionEvent = null;
mLastMotionEvent = null;
} else {
- mFirstRecentMotionEvent = mRecentMotionEvents.get(0);
- mLastMotionEvent = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1);
+ mFirstRecentMotionEvent = recentMotionEvents.get(0);
+ mLastMotionEvent = recentMotionEvents.get(recentMotionEvents.size() - 1);
}
calculateAngleInternal();
@@ -249,6 +274,17 @@ public class FalsingDataProvider {
mDirty = false;
}
+ private boolean shouldDropEvent(MotionEvent event) {
+ if (mRecentMotionEvents.size() < 3) return false;
+
+ MotionEvent lastEvent = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1);
+ boolean isCompletingGesture = event.getActionMasked() == MotionEvent.ACTION_UP
+ && lastEvent.getActionMasked() == MotionEvent.ACTION_MOVE;
+ boolean isRecentEvent =
+ event.getEventTime() - lastEvent.getEventTime() < DROP_EVENT_THRESHOLD_MS;
+ return isCompletingGesture && isRecentEvent;
+ }
+
private void calculateAngleInternal() {
if (mRecentMotionEvents.size() < 2) {
mAngle = Float.MAX_VALUE;
@@ -380,8 +416,8 @@ public class FalsingDataProvider {
return mBatteryController.isWirelessCharging() || mDockManager.isDocked();
}
- public boolean isFolded() {
- return Boolean.TRUE.equals(mFoldStateListener.getFolded());
+ public boolean isUnfolded() {
+ return Boolean.FALSE.equals(mFoldStateListener.getFolded());
}
/** Implement to be alerted abotu the beginning and ending of falsing tracking. */
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java b/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java
index e5da38936593..addd8e26490a 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java
@@ -183,7 +183,7 @@ public class TimeLimitedMotionEventBuffer implements List<MotionEvent> {
@Override
public List<MotionEvent> subList(int fromIndex, int toIndex) {
- throw new UnsupportedOperationException();
+ return mMotionEvents.subList(fromIndex, toIndex);
}
class Iter implements ListIterator<MotionEvent> {
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index c214f5341450..e049ae09b1de 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -263,10 +263,11 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
@Override // ClipboardListener.ClipboardOverlay
public void setClipData(ClipData data, String source) {
ClipboardModel model = ClipboardModel.fromClipData(mContext, mClipboardUtils, data, source);
- if (mExitAnimator != null && mExitAnimator.isRunning()) {
+ boolean wasExiting = (mExitAnimator != null && mExitAnimator.isRunning());
+ if (wasExiting) {
mExitAnimator.cancel();
}
- boolean shouldAnimate = !model.dataMatches(mClipboardModel);
+ boolean shouldAnimate = !model.dataMatches(mClipboardModel) || wasExiting;
mClipboardModel = model;
mClipboardLogger.setClipSource(mClipboardModel.getSource());
if (shouldAnimate) {
@@ -313,15 +314,19 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
mOnPreviewTapped = this::editText;
break;
case IMAGE:
- if (model.isSensitive() || model.loadThumbnail(mContext) != null) {
- mView.showImagePreview(
- model.isSensitive() ? null : model.loadThumbnail(mContext));
- mView.setEditAccessibilityAction(true);
- mOnPreviewTapped = () -> editImage(model.getUri());
- } else {
- // image loading failed
- mView.showDefaultTextPreview();
- }
+ mBgExecutor.execute(() -> {
+ if (model.isSensitive() || model.loadThumbnail(mContext) != null) {
+ mView.post(() -> {
+ mView.showImagePreview(
+ model.isSensitive() ? null : model.loadThumbnail(mContext));
+ mView.setEditAccessibilityAction(true);
+ });
+ mOnPreviewTapped = () -> editImage(model.getUri());
+ } else {
+ // image loading failed
+ mView.post(mView::showDefaultTextPreview);
+ }
+ });
break;
case URI:
case OTHER:
@@ -346,9 +351,20 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
}
private void animateFromMinimized() {
- mIsMinimized = false;
- setExpandedView();
- animateIn();
+ if (mEnterAnimator != null && mEnterAnimator.isRunning()) {
+ mEnterAnimator.cancel();
+ }
+ mEnterAnimator = mView.getMinimizedFadeoutAnimation();
+ mEnterAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mIsMinimized = false;
+ setExpandedView();
+ animateIn();
+ }
+ });
+ mEnterAnimator.start();
}
private String getAccessibilityAnnouncement(ClipboardModel.Type type) {
@@ -363,15 +379,15 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
private void classifyText(ClipboardModel model) {
mBgExecutor.execute(() -> {
- Optional<RemoteAction> remoteAction = mClipboardUtils.getAction(
- model.getText(), model.getTextLinks(), model.getSource());
+ Optional<RemoteAction> remoteAction =
+ mClipboardUtils.getAction(model.getTextLinks(), model.getSource());
if (model.equals(mClipboardModel)) {
remoteAction.ifPresent(action -> {
mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_ACTION_SHOWN);
- mView.setActionChip(action, () -> {
+ mView.post(() -> mView.setActionChip(action, () -> {
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_ACTION_TAPPED);
animateOut();
- });
+ }));
});
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java
index a85f8b9357f5..25caaeac2c38 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java
@@ -39,6 +39,9 @@ import javax.inject.Inject;
class ClipboardOverlayUtils {
+ // minimum proportion of entire text an entity must take up, to be considered for smart actions
+ private static final float MINIMUM_ENTITY_PROPORTION = .8f;
+
private final TextClassifier mTextClassifier;
@Inject
@@ -65,19 +68,23 @@ class ClipboardOverlayUtils {
return false;
}
- public Optional<RemoteAction> getAction(CharSequence text, TextLinks textLinks, String source) {
- return getActions(text, textLinks).stream().filter(remoteAction -> {
+ public Optional<RemoteAction> getAction(TextLinks textLinks, String source) {
+ return getActions(textLinks).stream().filter(remoteAction -> {
ComponentName component = remoteAction.getActionIntent().getIntent().getComponent();
return component != null && !TextUtils.equals(source, component.getPackageName());
}).findFirst();
}
- private ArrayList<RemoteAction> getActions(CharSequence text, TextLinks textLinks) {
+ private ArrayList<RemoteAction> getActions(TextLinks textLinks) {
ArrayList<RemoteAction> actions = new ArrayList<>();
for (TextLinks.TextLink link : textLinks.getLinks()) {
- TextClassification classification = mTextClassifier.classifyText(
- text, link.getStart(), link.getEnd(), null);
- actions.addAll(classification.getActions());
+ // skip classification for incidental entities
+ if (link.getEnd() - link.getStart()
+ >= textLinks.getText().length() * MINIMUM_ENTITY_PROPORTION) {
+ TextClassification classification = mTextClassifier.classifyText(
+ textLinks.getText(), link.getStart(), link.getEnd(), null);
+ actions.addAll(classification.getActions());
+ }
}
return actions;
}
@@ -92,9 +99,13 @@ class ClipboardOverlayUtils {
private ArrayList<RemoteAction> getActions(ClipData.Item item) {
ArrayList<RemoteAction> actions = new ArrayList<>();
for (TextLinks.TextLink link : item.getTextLinks().getLinks()) {
- TextClassification classification = mTextClassifier.classifyText(
- item.getText(), link.getStart(), link.getEnd(), null);
- actions.addAll(classification.getActions());
+ // skip classification for incidental entities
+ if (link.getEnd() - link.getStart()
+ >= item.getText().length() * MINIMUM_ENTITY_PROPORTION) {
+ TextClassification classification = mTextClassifier.classifyText(
+ item.getText(), link.getStart(), link.getEnd(), null);
+ actions.addAll(classification.getActions());
+ }
}
return actions;
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
index f372bb4bc7f2..28c57d31a4f3 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
@@ -21,6 +21,7 @@ import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
@@ -286,6 +287,20 @@ public class ClipboardOverlayView extends DraggableConstraintLayout {
mActionChips.clear();
}
+ Animator getMinimizedFadeoutAnimation() {
+ ObjectAnimator anim = ObjectAnimator.ofFloat(mMinimizedPreview, "alpha", 1, 0);
+ anim.setDuration(66);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mMinimizedPreview.setVisibility(View.GONE);
+ mMinimizedPreview.setAlpha(1);
+ }
+ });
+ return anim;
+ }
+
Animator getEnterAnimation() {
if (mAccessibilityManager.isEnabled()) {
mDismissButton.setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt b/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
index a0b19dc5c96e..c0e1717ea014 100644
--- a/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
@@ -26,7 +26,6 @@ object ChannelExt {
/**
* Convenience wrapper around [SendChannel.trySend] that also logs on failure. This is the
* equivalent of calling:
- *
* ```
* sendChannel.trySend(element).onFailure {
* Log.e(
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java b/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
index 826253947ce1..1833202d64d4 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
@@ -110,7 +110,7 @@ public class SeekBarWithIconButtonsView extends LinearLayout {
mSeekbar.setOnSeekBarChangeListener(mSeekBarListener);
- mIconStart.setOnClickListener((view) -> {
+ mIconStartFrame.setOnClickListener((view) -> {
final int progress = mSeekbar.getProgress();
if (progress > 0) {
mSeekbar.setProgress(progress - 1);
@@ -118,7 +118,7 @@ public class SeekBarWithIconButtonsView extends LinearLayout {
}
});
- mIconEnd.setOnClickListener((view) -> {
+ mIconEndFrame.setOnClickListener((view) -> {
final int progress = mSeekbar.getProgress();
if (progress < mSeekbar.getMax()) {
mSeekbar.setProgress(progress + 1);
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
index b3c18fb3cd98..3744344421a9 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
@@ -86,6 +86,7 @@ internal constructor(wrapper: ControlsFavoritePersistenceWrapper) {
*
* When the favorites for that application are returned, they will be removed from the auxiliary
* file immediately, so they won't be retrieved again.
+ *
* @param componentName the name of the service that provided the controls
* @return a list of structures with favorites
*/
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
index 822190f21da1..2d37c292a6b8 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -166,6 +166,13 @@ interface ControlsController : UserAwareController {
)
/**
+ * Removes favorites for a given component
+ * @param componentName the name of the service that provides the [Control]
+ * @return true when favorites is scheduled for deletion
+ */
+ fun removeFavorites(componentName: ComponentName): Boolean
+
+ /**
* Replaces the favorites for the given structure.
*
* Calling this method will eliminate the previous selection of favorites and replace it with a
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 278ee7079720..e8c97bf77271 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -37,6 +37,7 @@ import com.android.systemui.controls.ControlStatus
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.SelectedComponentRepository
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.controls.ui.SelectedItem
import com.android.systemui.dagger.SysUISingleton
@@ -55,16 +56,17 @@ import javax.inject.Inject
@SysUISingleton
class ControlsControllerImpl @Inject constructor (
- private val context: Context,
- @Background private val executor: DelayableExecutor,
- private val uiController: ControlsUiController,
- private val bindingController: ControlsBindingController,
- private val listingController: ControlsListingController,
- private val userFileManager: UserFileManager,
- private val userTracker: UserTracker,
- private val authorizedPanelsRepository: AuthorizedPanelsRepository,
- optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>,
- dumpManager: DumpManager,
+ private val context: Context,
+ @Background private val executor: DelayableExecutor,
+ private val uiController: ControlsUiController,
+ private val selectedComponentRepository: SelectedComponentRepository,
+ private val bindingController: ControlsBindingController,
+ private val listingController: ControlsListingController,
+ private val userFileManager: UserFileManager,
+ private val userTracker: UserTracker,
+ private val authorizedPanelsRepository: AuthorizedPanelsRepository,
+ optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>,
+ dumpManager: DumpManager,
) : Dumpable, ControlsController {
companion object {
@@ -497,6 +499,18 @@ class ControlsControllerImpl @Inject constructor (
}
}
+ override fun removeFavorites(componentName: ComponentName): Boolean {
+ if (!confirmAvailability()) return false
+
+ executor.execute {
+ if (Favorites.removeStructures(componentName)) {
+ persistenceWrapper.storeFavorites(Favorites.getAllStructures())
+ }
+ authorizedPanelsRepository.removeAuthorizedPanels(setOf(componentName.packageName))
+ }
+ return true
+ }
+
override fun replaceFavoritesForStructure(structureInfo: StructureInfo) {
if (!confirmAvailability()) return
executor.execute {
@@ -559,7 +573,9 @@ class ControlsControllerImpl @Inject constructor (
}
override fun setPreferredSelection(selectedItem: SelectedItem) {
- uiController.updatePreferences(selectedItem)
+ selectedComponentRepository.setSelectedComponent(
+ SelectedComponentRepository.SelectedComponent(selectedItem)
+ )
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
@@ -655,10 +671,11 @@ private object Favorites {
return true
}
- fun removeStructures(componentName: ComponentName) {
+ fun removeStructures(componentName: ComponentName): Boolean {
val newFavMap = favMap.toMutableMap()
- newFavMap.remove(componentName)
+ val removed = newFavMap.remove(componentName) != null
favMap = newFavMap
+ return removed
}
fun addFavorite(
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 72c3a943c30b..217f4d89e24c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -84,7 +84,7 @@ class ControlsProviderLifecycleManager(
private val BIND_FLAGS_PANEL = Context.BIND_AUTO_CREATE or Context.BIND_NOT_PERCEPTIBLE
}
- private val intent = Intent().apply {
+ private val intent = Intent(ControlsProviderService.SERVICE_CONTROLS).apply {
component = componentName
putExtra(CALLBACK_BUNDLE, Bundle().apply {
putBinder(CALLBACK_TOKEN, token)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
index d949d1119222..2af49aa5fa1a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
@@ -36,6 +36,8 @@ import com.android.systemui.controls.management.ControlsProviderSelectorActivity
import com.android.systemui.controls.management.ControlsRequestDialog
import com.android.systemui.controls.panels.AuthorizedPanelsRepository
import com.android.systemui.controls.panels.AuthorizedPanelsRepositoryImpl
+import com.android.systemui.controls.panels.SelectedComponentRepository
+import com.android.systemui.controls.panels.SelectedComponentRepositoryImpl
import com.android.systemui.controls.settings.ControlsSettingsDialogManager
import com.android.systemui.controls.settings.ControlsSettingsDialogManagerImpl
import com.android.systemui.controls.ui.ControlActionCoordinator
@@ -114,6 +116,11 @@ abstract class ControlsModule {
repository: AuthorizedPanelsRepositoryImpl
): AuthorizedPanelsRepository
+ @Binds
+ abstract fun providePreferredPanelRepository(
+ repository: SelectedComponentRepositoryImpl
+ ): SelectedComponentRepository
+
@BindsOptionalOf
abstract fun optionalPersistenceWrapper(): ControlsFavoritePersistenceWrapper
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
index b9f16665944f..cf5ccc5bbf6c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
@@ -16,6 +16,7 @@
package com.android.systemui.controls.management
+import android.annotation.WorkerThread
import android.content.ComponentName
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.util.UserAwareController
@@ -33,6 +34,9 @@ interface ControlsListingController :
*/
fun getCurrentServices(): List<ControlsServiceInfo>
+ @WorkerThread
+ fun forceReload()
+
/**
* Get the app label for a given component.
*
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
index c81a2c7e2ac6..8ba060e02c3d 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
@@ -16,8 +16,11 @@
package com.android.systemui.controls.management
+import android.annotation.WorkerThread
import android.content.ComponentName
import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
import android.os.UserHandle
import android.service.controls.ControlsProviderService
import android.util.Log
@@ -65,7 +68,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor(
private val serviceListingBuilder: (Context) -> ServiceListing,
private val userTracker: UserTracker,
dumpManager: DumpManager,
- featureFlags: FeatureFlags
+ private val featureFlags: FeatureFlags
) : ControlsListingController, Dumpable {
@Inject
@@ -97,18 +100,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor(
// After here, `list` is not captured, so we don't risk modifying it outside of the callback
backgroundExecutor.execute {
if (userChangeInProgress.get() > 0) return@execute
- if (featureFlags.isEnabled(Flags.USE_APP_PANELS)) {
- val allowAllApps = featureFlags.isEnabled(Flags.APP_PANELS_ALL_APPS_ALLOWED)
- newServices.forEach {
- it.resolvePanelActivity(allowAllApps) }
- }
-
- if (newServices != availableServices) {
- availableServices = newServices
- callbacks.forEach {
- it.onServicesUpdated(getCurrentServices())
- }
- }
+ updateServices(newServices)
}
}
@@ -120,6 +112,21 @@ class ControlsListingControllerImpl @VisibleForTesting constructor(
serviceListing.reload()
}
+ private fun updateServices(newServices: List<ControlsServiceInfo>) {
+ if (featureFlags.isEnabled(Flags.USE_APP_PANELS)) {
+ val allowAllApps = featureFlags.isEnabled(Flags.APP_PANELS_ALL_APPS_ALLOWED)
+ newServices.forEach {
+ it.resolvePanelActivity(allowAllApps) }
+ }
+
+ if (newServices != availableServices) {
+ availableServices = newServices
+ callbacks.forEach {
+ it.onServicesUpdated(getCurrentServices())
+ }
+ }
+ }
+
override fun changeUser(newUser: UserHandle) {
userChangeInProgress.incrementAndGet()
serviceListing.setListening(false)
@@ -178,6 +185,23 @@ class ControlsListingControllerImpl @VisibleForTesting constructor(
override fun getCurrentServices(): List<ControlsServiceInfo> =
availableServices.map(ControlsServiceInfo::copy)
+ @WorkerThread
+ override fun forceReload() {
+ val packageManager = context.packageManager
+ val intent = Intent(ControlsProviderService.SERVICE_CONTROLS)
+ val user = userTracker.userHandle
+ val flags = PackageManager.GET_SERVICES or
+ PackageManager.GET_META_DATA or
+ PackageManager.MATCH_DIRECT_BOOT_UNAWARE or
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ val services = packageManager.queryIntentServicesAsUser(
+ intent,
+ PackageManager.ResolveInfoFlags.of(flags.toLong()),
+ user
+ ).map { ControlsServiceInfo(userTracker.userContext, it.serviceInfo) }
+ updateServices(services)
+ }
+
/**
* Get the localized label for the component.
*
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
index 3e672f391e81..ae9c37aa0e7b 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
@@ -26,6 +26,14 @@ interface AuthorizedPanelsRepository {
/** A set of package names that the user has previously authorized to show panels. */
fun getAuthorizedPanels(): Set<String>
+ /** Preferred applications to query controls suggestions from */
+ fun getPreferredPackages(): Set<String>
+
/** Adds [packageNames] to the set of packages that the user has authorized to show panels. */
fun addAuthorizedPanels(packageNames: Set<String>)
+
+ /**
+ * Removes [packageNames] from the set of packages that the user has authorized to show panels.
+ */
+ fun removeAuthorizedPanels(packageNames: Set<String>)
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
index f7e43a77b573..5c2402ba4149 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
@@ -20,6 +20,8 @@ package com.android.systemui.controls.panels
import android.content.Context
import android.content.SharedPreferences
import com.android.systemui.R
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
@@ -30,17 +32,28 @@ class AuthorizedPanelsRepositoryImpl
constructor(
private val context: Context,
private val userFileManager: UserFileManager,
- private val userTracker: UserTracker
+ private val userTracker: UserTracker,
+ private val featureFlags: FeatureFlags,
) : AuthorizedPanelsRepository {
override fun getAuthorizedPanels(): Set<String> {
return getAuthorizedPanelsInternal(instantiateSharedPrefs())
}
+ override fun getPreferredPackages(): Set<String> =
+ context.resources.getStringArray(R.array.config_controlsPreferredPackages).toSet()
+
override fun addAuthorizedPanels(packageNames: Set<String>) {
addAuthorizedPanelsInternal(instantiateSharedPrefs(), packageNames)
}
+ override fun removeAuthorizedPanels(packageNames: Set<String>) {
+ with(instantiateSharedPrefs()) {
+ val currentSet = getAuthorizedPanelsInternal(this)
+ edit().putStringSet(KEY, currentSet - packageNames).apply()
+ }
+ }
+
private fun getAuthorizedPanelsInternal(sharedPreferences: SharedPreferences): Set<String> {
return sharedPreferences.getStringSet(KEY, emptySet())!!
}
@@ -61,17 +74,19 @@ constructor(
userTracker.userId,
)
- // If we've never run this (i.e., the key doesn't exist), add the default packages
- if (sharedPref.getStringSet(KEY, null) == null) {
- sharedPref
- .edit()
- .putStringSet(
- KEY,
- context.resources
- .getStringArray(R.array.config_controlsPreferredPackages)
- .toSet()
- )
- .apply()
+ // We should add default packages in two cases:
+ // 1) We've never run this
+ // 2) APP_PANELS_REMOVE_APPS_ALLOWED got disabled after user removed all apps
+ val needToSetup =
+ if (featureFlags.isEnabled(Flags.APP_PANELS_REMOVE_APPS_ALLOWED)) {
+ sharedPref.getStringSet(KEY, null) == null
+ } else {
+ // There might be an empty set that need to be overridden after the feature has been
+ // turned off after being turned on
+ sharedPref.getStringSet(KEY, null).isNullOrEmpty()
+ }
+ if (needToSetup) {
+ sharedPref.edit().putStringSet(KEY, getPreferredPackages()).apply()
}
return sharedPref
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepository.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepository.kt
new file mode 100644
index 000000000000..5bb6eece9098
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepository.kt
@@ -0,0 +1,64 @@
+/*
+ * 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.controls.panels
+
+import android.content.ComponentName
+import com.android.systemui.controls.ui.ControlsUiController
+import com.android.systemui.controls.ui.SelectedItem
+import com.android.systemui.flags.Flags
+
+/** Stores user-selected preferred component. */
+interface SelectedComponentRepository {
+
+ /**
+ * Returns currently set preferred component, or null when nothing is set. Consider using
+ * [ControlsUiController.getPreferredSelectedItem] to get domain specific data
+ */
+ fun getSelectedComponent(): SelectedComponent?
+
+ /** Sets preferred component. Use [getSelectedComponent] to get current one */
+ fun setSelectedComponent(selectedComponent: SelectedComponent)
+
+ /** Clears current preferred component. [getSelectedComponent] will return null afterwards */
+ fun removeSelectedComponent()
+
+ /**
+ * Return true when default preferred component should be set up and false the otherwise. This
+ * is always true when [Flags.APP_PANELS_REMOVE_APPS_ALLOWED] is disabled
+ */
+ fun shouldAddDefaultComponent(): Boolean
+
+ /**
+ * Sets if default component should be added. This is ignored when
+ * [Flags.APP_PANELS_REMOVE_APPS_ALLOWED] is disabled
+ */
+ fun setShouldAddDefaultComponent(shouldAdd: Boolean)
+
+ data class SelectedComponent(
+ val name: String,
+ val componentName: ComponentName?,
+ val isPanel: Boolean,
+ ) {
+ constructor(
+ selectedItem: SelectedItem
+ ) : this(
+ name = selectedItem.name.toString(),
+ componentName = selectedItem.componentName,
+ isPanel = selectedItem is SelectedItem.PanelItem,
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.kt
new file mode 100644
index 000000000000..0fb5b66ef93c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.panels
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.SharedPreferences
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
+import javax.inject.Inject
+
+@SysUISingleton
+class SelectedComponentRepositoryImpl
+@Inject
+constructor(
+ private val userFileManager: UserFileManager,
+ private val userTracker: UserTracker,
+ private val featureFlags: FeatureFlags,
+) : SelectedComponentRepository {
+
+ private companion object {
+ const val PREF_COMPONENT = "controls_component"
+ const val PREF_STRUCTURE_OR_APP_NAME = "controls_structure"
+ const val PREF_IS_PANEL = "controls_is_panel"
+ const val SHOULD_ADD_DEFAULT_PANEL = "should_add_default_panel"
+ }
+
+ private val sharedPreferences: SharedPreferences
+ get() =
+ userFileManager.getSharedPreferences(
+ fileName = DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
+ mode = Context.MODE_PRIVATE,
+ userId = userTracker.userId
+ )
+
+ override fun getSelectedComponent(): SelectedComponentRepository.SelectedComponent? {
+ with(sharedPreferences) {
+ val componentString = getString(PREF_COMPONENT, null) ?: return null
+ return SelectedComponentRepository.SelectedComponent(
+ name = getString(PREF_STRUCTURE_OR_APP_NAME, "")!!,
+ componentName = ComponentName.unflattenFromString(componentString),
+ isPanel = getBoolean(PREF_IS_PANEL, false)
+ )
+ }
+ }
+
+ override fun setSelectedComponent(
+ selectedComponent: SelectedComponentRepository.SelectedComponent
+ ) {
+ sharedPreferences
+ .edit()
+ .putString(PREF_COMPONENT, selectedComponent.componentName?.flattenToString())
+ .putString(PREF_STRUCTURE_OR_APP_NAME, selectedComponent.name)
+ .putBoolean(PREF_IS_PANEL, selectedComponent.isPanel)
+ .apply()
+ }
+
+ override fun removeSelectedComponent() {
+ sharedPreferences
+ .edit()
+ .remove(PREF_COMPONENT)
+ .remove(PREF_STRUCTURE_OR_APP_NAME)
+ .remove(PREF_IS_PANEL)
+ .apply()
+ }
+
+ override fun shouldAddDefaultComponent(): Boolean =
+ if (featureFlags.isEnabled(Flags.APP_PANELS_REMOVE_APPS_ALLOWED)) {
+ sharedPreferences.getBoolean(SHOULD_ADD_DEFAULT_PANEL, true)
+ } else {
+ true
+ }
+
+ override fun setShouldAddDefaultComponent(shouldAdd: Boolean) {
+ sharedPreferences.edit().putBoolean(SHOULD_ADD_DEFAULT_PANEL, shouldAdd).apply()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
index bb2e2d701aa0..06d4a0888197 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
@@ -38,7 +38,6 @@ import javax.inject.Inject
/**
* Manager to display a dialog to prompt user to enable controls related Settings:
- *
* * [Settings.Secure.LOCKSCREEN_SHOW_CONTROLS]
* * [Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS]
*/
@@ -46,20 +45,19 @@ interface ControlsSettingsDialogManager {
/**
* Shows the corresponding dialog. In order for a dialog to appear, the following must be true
- *
* * At least one of the Settings in [ControlsSettingsRepository] are `false`.
* * The dialog has not been seen by the user too many times (as defined by
- * [MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG]).
+ * [MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG]).
*
* When the dialogs are shown, the following outcomes are possible:
* * User cancels the dialog by clicking outside or going back: we register that the dialog was
- * seen but the settings don't change.
+ * seen but the settings don't change.
* * User responds negatively to the dialog: we register that the user doesn't want to change
- * the settings (dialog will not appear again) and the settings don't change.
+ * the settings (dialog will not appear again) and the settings don't change.
* * User responds positively to the dialog: the settings are set to `true` and the dialog will
- * not appear again.
+ * not appear again.
* * SystemUI closes the dialogs (for example, the activity showing it is closed). In this case,
- * we don't modify anything.
+ * we don't modify anything.
*
* Of those four scenarios, only the first three will cause [onAttemptCompleted] to be called.
* It will also be called if the dialogs are not shown.
diff --git a/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt b/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
index 9d99253de741..461caccc86d3 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
@@ -18,17 +18,17 @@
package com.android.systemui.controls.start
import android.content.Context
-import android.content.res.Resources
import android.os.UserHandle
+import androidx.annotation.WorkerThread
import com.android.systemui.CoreStartable
-import com.android.systemui.R
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.dagger.ControlsComponent
import com.android.systemui.controls.management.ControlsListingController
+import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.SelectedComponentRepository
import com.android.systemui.controls.ui.SelectedItem
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.settings.UserTracker
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -37,7 +37,7 @@ import javax.inject.Inject
* Started with SystemUI to perform early operations for device controls subsystem (only if enabled)
*
* In particular, it will perform the following:
- * * If there is no preferred selection for provider and at least one of the preferred packages
+ * * If there is no preferred selection for provider and at least one of the preferred packages
* provides a panel, it will select the first one that does.
* * If the preferred selection provides a panel, it will bind to that service (to reduce latency on
* displaying the panel).
@@ -48,10 +48,11 @@ import javax.inject.Inject
class ControlsStartable
@Inject
constructor(
- @Main private val resources: Resources,
- @Background private val executor: Executor,
- private val controlsComponent: ControlsComponent,
- private val userTracker: UserTracker
+ @Background private val executor: Executor,
+ private val controlsComponent: ControlsComponent,
+ private val userTracker: UserTracker,
+ private val authorizedPanelsRepository: AuthorizedPanelsRepository,
+ private val selectedComponentRepository: SelectedComponentRepository,
) : CoreStartable {
// These two controllers can only be accessed after `start` method once we've checked if the
@@ -75,22 +76,27 @@ constructor(
// Controls is disabled, we don't need this anymore
return
}
- startForUser()
+ executor.execute(this::startForUser)
userTracker.addCallback(userTrackerCallback, executor)
}
+ @WorkerThread
private fun startForUser() {
+ controlsListingController.forceReload()
selectDefaultPanelIfNecessary()
bindToPanel()
}
private fun selectDefaultPanelIfNecessary() {
+ if (!selectedComponentRepository.shouldAddDefaultComponent()) {
+ return
+ }
val currentSelection = controlsController.getPreferredSelection()
if (currentSelection == SelectedItem.EMPTY_SELECTION) {
val availableServices = controlsListingController.getCurrentServices()
val panels = availableServices.filter { it.panelActivity != null }
- resources
- .getStringArray(R.array.config_controlsPreferredPackages)
+ authorizedPanelsRepository
+ .getPreferredPackages()
// Looking for the first element in the string array such that there is one package
// that has a panel. It will return null if there are no packages in the array,
// or if no packages in the array have a panel associated with it.
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
index 3a3f9b4e5265..bf0a69296dfd 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -68,7 +68,7 @@ class ControlsActivity @Inject constructor(
getLifecycle().addObserver(
ControlsAnimations.observerForAnimations(
- requireViewById<ViewGroup>(R.id.control_detail_root),
+ requireViewById(R.id.control_detail_root),
window,
intent,
!featureFlags.isEnabled(Flags.USE_APP_PANELS)
@@ -95,7 +95,7 @@ class ControlsActivity @Inject constructor(
override fun onStart() {
super.onStart()
- parent = requireViewById<ViewGroup>(R.id.global_actions_controls)
+ parent = requireViewById(R.id.control_detail_root)
parent.alpha = 0f
if (featureFlags.isEnabled(Flags.USE_APP_PANELS) && !keyguardStateController.isUnlocked) {
controlsSettingsDialogManager.maybeShowDialog(this) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt
new file mode 100644
index 000000000000..d6cfb79101d7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.controls.ui
+
+import android.app.Dialog
+import android.content.Context
+import android.content.DialogInterface
+import com.android.systemui.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import java.util.function.Consumer
+import javax.inject.Inject
+
+class ControlsDialogsFactory(private val internalDialogFactory: (Context) -> SystemUIDialog) {
+
+ @Inject constructor() : this({ SystemUIDialog(it) })
+
+ fun createRemoveAppDialog(
+ context: Context,
+ appName: CharSequence,
+ response: Consumer<Boolean>
+ ): Dialog {
+ val listener =
+ DialogInterface.OnClickListener { _, which ->
+ response.accept(which == DialogInterface.BUTTON_POSITIVE)
+ }
+ return internalDialogFactory(context).apply {
+ setTitle(context.getString(R.string.controls_panel_remove_app_authorization, appName))
+ setCanceledOnTouchOutside(true)
+ setOnCancelListener { response.accept(false) }
+ setPositiveButton(R.string.controls_dialog_remove, listener)
+ setNeutralButton(R.string.cancel, listener)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
index 58673bb6f567..0d5311752ab9 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
@@ -64,8 +64,6 @@ interface ControlsUiController {
* This element will be the one that appears when the user first opens the controls activity.
*/
fun getPreferredSelectedItem(structures: List<StructureInfo>): SelectedItem
-
- fun updatePreferences(selectedItem: SelectedItem)
}
sealed class SelectedItem {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 9405c602caf7..5da86de933e6 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.app.Activity
import android.app.ActivityOptions
+import android.app.Dialog
import android.app.PendingIntent
import android.content.ComponentName
import android.content.Context
@@ -52,7 +53,6 @@ import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.controls.ControlsMetricsLogger
import com.android.systemui.controls.ControlsServiceInfo
-import com.android.systemui.controls.settings.ControlsSettingsRepository
import com.android.systemui.controls.CustomIconCache
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.StructureInfo
@@ -64,6 +64,8 @@ import com.android.systemui.controls.management.ControlsFavoritingActivity
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.management.ControlsProviderSelectorActivity
import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.SelectedComponentRepository
+import com.android.systemui.controls.settings.ControlsSettingsRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -72,9 +74,7 @@ import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.globalactions.GlobalActionsPopupMenu
import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
-import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.asIndenting
import com.android.systemui.util.concurrency.DelayableExecutor
@@ -97,24 +97,22 @@ class ControlsUiControllerImpl @Inject constructor (
@Main val uiExecutor: DelayableExecutor,
@Background val bgExecutor: DelayableExecutor,
val controlsListingController: Lazy<ControlsListingController>,
- val controlActionCoordinator: ControlActionCoordinator,
+ private val controlActionCoordinator: ControlActionCoordinator,
private val activityStarter: ActivityStarter,
private val iconCache: CustomIconCache,
private val controlsMetricsLogger: ControlsMetricsLogger,
private val keyguardStateController: KeyguardStateController,
- private val userFileManager: UserFileManager,
private val userTracker: UserTracker,
private val taskViewFactory: Optional<TaskViewFactory>,
private val controlsSettingsRepository: ControlsSettingsRepository,
private val authorizedPanelsRepository: AuthorizedPanelsRepository,
+ private val selectedComponentRepository: SelectedComponentRepository,
private val featureFlags: FeatureFlags,
+ private val dialogsFactory: ControlsDialogsFactory,
dumpManager: DumpManager
) : ControlsUiController, Dumpable {
companion object {
- private const val PREF_COMPONENT = "controls_component"
- private const val PREF_STRUCTURE_OR_APP_NAME = "controls_structure"
- private const val PREF_IS_PANEL = "controls_is_panel"
private const val FADE_IN_MILLIS = 200L
@@ -122,6 +120,7 @@ class ControlsUiControllerImpl @Inject constructor (
private const val ADD_CONTROLS_ID = 1L
private const val ADD_APP_ID = 2L
private const val EDIT_CONTROLS_ID = 3L
+ private const val REMOVE_APP_ID = 4L
}
private var selectedItem: SelectedItem = SelectedItem.EMPTY_SELECTION
@@ -135,12 +134,6 @@ class ControlsUiControllerImpl @Inject constructor (
private val popupThemedContext = ContextThemeWrapper(context, R.style.Control_ListPopupWindow)
private var retainCache = false
private var lastSelections = emptyList<SelectionItem>()
- private val sharedPreferences
- get() = userFileManager.getSharedPreferences(
- fileName = DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
- mode = 0,
- userId = userTracker.userId
- )
private var taskViewController: PanelTaskViewController? = null
@@ -151,6 +144,7 @@ class ControlsUiControllerImpl @Inject constructor (
private var openAppIntent: Intent? = null
private var overflowMenuAdapter: BaseAdapter? = null
+ private var removeAppDialog: Dialog? = null
private val onSeedingComplete = Consumer<Boolean> {
accepted ->
@@ -330,6 +324,29 @@ class ControlsUiControllerImpl @Inject constructor (
}
}
+ @VisibleForTesting
+ internal fun startRemovingApp(componentName: ComponentName, appName: CharSequence) {
+ removeAppDialog?.cancel()
+ removeAppDialog = dialogsFactory.createRemoveAppDialog(context, appName) {
+ if (!controlsController.get().removeFavorites(componentName)) {
+ return@createRemoveAppDialog
+ }
+
+ if (selectedComponentRepository.getSelectedComponent()?.componentName ==
+ componentName) {
+ selectedComponentRepository.removeSelectedComponent()
+ }
+
+ val selectedItem = getPreferredSelectedItem(controlsController.get().getFavorites())
+ if (selectedItem == SelectedItem.EMPTY_SELECTION) {
+ // User removed the last panel. In this case we start app selection flow and don't
+ // want to auto-add it again
+ selectedComponentRepository.setShouldAddDefaultComponent(false)
+ }
+ reload(parent)
+ }.apply { show() }
+ }
+
private fun startTargetedActivity(si: StructureInfo, klazz: Class<*>) {
val i = Intent(activityContext, klazz)
putIntentExtras(i, si)
@@ -433,7 +450,10 @@ class ControlsUiControllerImpl @Inject constructor (
val currentApps = panelsAndStructures.map { it.componentName }.toSet()
val allApps = controlsListingController.get()
.getCurrentServices().map { it.componentName }.toSet()
- createMenu(extraApps = (allApps - currentApps).isNotEmpty())
+ createMenu(
+ selectionItem = selectionItem,
+ extraApps = (allApps - currentApps).isNotEmpty(),
+ )
}
private fun createPanelView(componentName: ComponentName) {
@@ -472,7 +492,7 @@ class ControlsUiControllerImpl @Inject constructor (
}
}
- private fun createMenu(extraApps: Boolean) {
+ private fun createMenu(selectionItem: SelectionItem, extraApps: Boolean) {
val isPanel = selectedItem is SelectedItem.PanelItem
val selectedStructure = (selectedItem as? SelectedItem.StructureItem)?.structure
?: EMPTY_STRUCTURE
@@ -490,6 +510,12 @@ class ControlsUiControllerImpl @Inject constructor (
ADD_APP_ID
))
}
+ if (featureFlags.isEnabled(Flags.APP_PANELS_REMOVE_APPS_ALLOWED)) {
+ add(OverflowMenuAdapter.MenuItem(
+ context.getText(R.string.controls_menu_remove),
+ REMOVE_APP_ID,
+ ))
+ }
} else {
add(OverflowMenuAdapter.MenuItem(
context.getText(R.string.controls_menu_add),
@@ -529,6 +555,9 @@ class ControlsUiControllerImpl @Inject constructor (
ADD_APP_ID -> startProviderSelectorActivity()
ADD_CONTROLS_ID -> startFavoritingActivity(selectedStructure)
EDIT_CONTROLS_ID -> startEditingActivity(selectedStructure)
+ REMOVE_APP_ID -> startRemovingApp(
+ selectionItem.componentName, selectionItem.appName
+ )
}
dismiss()
}
@@ -546,8 +575,12 @@ class ControlsUiControllerImpl @Inject constructor (
RenderInfo.registerComponentIcon(it.componentName, it.icon)
}
- var adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply {
- addAll(items)
+ val adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply {
+ add(selected)
+ addAll(items
+ .filter { it !== selected }
+ .sortedBy { it.appName.toString() }
+ )
}
val iconSize = context.resources
@@ -668,29 +701,22 @@ class ControlsUiControllerImpl @Inject constructor (
}
override fun getPreferredSelectedItem(structures: List<StructureInfo>): SelectedItem {
- val sp = sharedPreferences
-
- val component = sp.getString(PREF_COMPONENT, null)?.let {
- ComponentName.unflattenFromString(it)
- } ?: EMPTY_COMPONENT
- val name = sp.getString(PREF_STRUCTURE_OR_APP_NAME, "")!!
- val isPanel = sp.getBoolean(PREF_IS_PANEL, false)
- return if (isPanel) {
- SelectedItem.PanelItem(name, component)
+ val preferredPanel = selectedComponentRepository.getSelectedComponent()
+ val component = preferredPanel?.componentName ?: EMPTY_COMPONENT
+ return if (preferredPanel?.isPanel == true) {
+ SelectedItem.PanelItem(preferredPanel.name, component)
} else {
if (structures.isEmpty()) return SelectedItem.EMPTY_SELECTION
SelectedItem.StructureItem(structures.firstOrNull {
- component == it.componentName && name == it.structure
- } ?: structures.get(0))
+ component == it.componentName && preferredPanel?.name == it.structure
+ } ?: structures[0])
}
}
- override fun updatePreferences(selectedItem: SelectedItem) {
- sharedPreferences.edit()
- .putString(PREF_COMPONENT, selectedItem.componentName.flattenToString())
- .putString(PREF_STRUCTURE_OR_APP_NAME, selectedItem.name.toString())
- .putBoolean(PREF_IS_PANEL, selectedItem is SelectedItem.PanelItem)
- .apply()
+ private fun updatePreferences(selectedItem: SelectedItem) {
+ selectedComponentRepository.setSelectedComponent(
+ SelectedComponentRepository.SelectedComponent(selectedItem)
+ )
}
private fun maybeUpdateSelectedItem(item: SelectionItem): Boolean {
@@ -728,6 +754,7 @@ class ControlsUiControllerImpl @Inject constructor (
it.value.dismiss()
}
controlActionCoordinator.closeDialogs()
+ removeAppDialog?.cancel()
}
override fun hide(parent: ViewGroup) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
index 3b6ab20e39d4..78e87cafc4f2 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
@@ -71,7 +71,7 @@ class PanelTaskViewController(
taskView.post {
val roundedCorner =
activityContext.resources.getDimensionPixelSize(
- R.dimen.notification_corner_radius
+ R.dimen.controls_panel_corner_radius
)
val radii = FloatArray(8) { roundedCorner.toFloat() }
taskView.background =
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
index fb016911f913..cb2d6732b130 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
@@ -29,6 +29,7 @@ import com.android.systemui.sensorprivacy.television.TvUnblockSensorActivity;
import com.android.systemui.settings.brightness.BrightnessDialog;
import com.android.systemui.statusbar.tv.notifications.TvNotificationPanelActivity;
import com.android.systemui.tuner.TunerActivity;
+import com.android.systemui.usb.UsbAccessoryUriActivity;
import com.android.systemui.usb.UsbConfirmActivity;
import com.android.systemui.usb.UsbDebuggingActivity;
import com.android.systemui.usb.UsbDebuggingSecondaryUserActivity;
@@ -94,6 +95,12 @@ public abstract class DefaultActivityBinder {
@ClassKey(UsbConfirmActivity.class)
public abstract Activity bindUsbConfirmActivity(UsbConfirmActivity activity);
+ /** Inject into UsbAccessoryUriActivity. */
+ @Binds
+ @IntoMap
+ @ClassKey(UsbAccessoryUriActivity.class)
+ public abstract Activity bindUsbAccessoryUriActivity(UsbAccessoryUriActivity activity);
+
/** Inject into CreateUserActivity. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index 03a1dc068d3d..378b7bb618f8 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -52,6 +52,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.dagger.StartCentralSurfacesModule;
+import com.android.systemui.statusbar.events.StatusBarEventsModule;
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.DozeServiceHost;
@@ -101,6 +102,7 @@ import dagger.Provides;
QSModule.class,
ReferenceScreenshotModule.class,
RotationLockModule.class,
+ StatusBarEventsModule.class,
StartCentralSurfacesModule.class,
VolumeModule.class
})
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 5b4ce065791d..05527bd2c843 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -70,11 +70,14 @@ import com.android.systemui.security.data.repository.SecurityRepositoryModule;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.dagger.MultiUserUtilsModule;
import com.android.systemui.shade.ShadeController;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolatorImpl;
import com.android.systemui.smartspace.dagger.SmartspaceModule;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.connectivity.ConnectivityModule;
+import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
@@ -255,6 +258,9 @@ public abstract class SystemUIModule {
@BindsOptionalOf
abstract FingerprintInteractiveToAuthProvider optionalFingerprintInteractiveToAuthProvider();
+ @BindsOptionalOf
+ abstract SystemStatusAnimationScheduler optionalSystemStatusAnimationScheduler();
+
@SysUISingleton
@Binds
abstract SystemClock bindSystemClock(SystemClockImpl systemClock);
@@ -302,4 +308,8 @@ public abstract class SystemUIModule {
@Binds
abstract FgsManagerController bindFgsManagerController(FgsManagerControllerImpl impl);
+
+ @Binds
+ abstract LargeScreenShadeInterpolator largeScreensShadeInterpolator(
+ LargeScreenShadeInterpolatorImpl impl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
index 84f83f1ae956..45ff963c2a9f 100644
--- a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
+++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
@@ -128,7 +128,6 @@ constructor(
*
* This is equivalent of creating a listener manually and adding an event handler for the given
* command, like so:
- *
* ```
* class Demoable {
* private val demoHandler = object : DemoMode {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index c3bd5d96590e..d0a92f0846d0 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -43,7 +43,6 @@ import com.android.systemui.util.concurrency.DelayableExecutor
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.launch
@@ -131,9 +130,17 @@ constructor(
}
}
- /** Starts the dream content and dream overlay entry animations. */
+ /**
+ * Starts the dream content and dream overlay entry animations.
+ *
+ * @param downwards if true, the entry animation translations downwards into position rather
+ * than upwards.
+ */
@JvmOverloads
- fun startEntryAnimations(animatorBuilder: () -> AnimatorSet = { AnimatorSet() }) {
+ fun startEntryAnimations(
+ downwards: Boolean,
+ animatorBuilder: () -> AnimatorSet = { AnimatorSet() }
+ ) {
cancelAnimations()
mAnimator =
@@ -153,7 +160,7 @@ constructor(
interpolator = Interpolators.LINEAR
),
translationYAnimator(
- from = mDreamInTranslationYDistance.toFloat(),
+ from = mDreamInTranslationYDistance.toFloat() * (if (downwards) -1 else 1),
to = 0f,
durationMs = mDreamInTranslationYDurationMs,
interpolator = Interpolators.EMPHASIZED_DECELERATE
@@ -167,6 +174,71 @@ constructor(
}
}
+ /**
+ * Starts the dream content and dream overlay exit animations.
+ *
+ * This should only be used when the low light dream is entering, animations to/from other SysUI
+ * views is controlled by `transitionViewModel`.
+ */
+ // TODO(b/256916668): integrate with the keyguard transition model once dream surfaces work is
+ // done.
+ @JvmOverloads
+ fun startExitAnimations(animatorBuilder: () -> AnimatorSet = { AnimatorSet() }): Animator {
+ cancelAnimations()
+
+ mAnimator =
+ animatorBuilder().apply {
+ playTogether(
+ translationYAnimator(
+ from = 0f,
+ to = -mDreamInTranslationYDistance.toFloat(),
+ durationMs = mDreamInTranslationYDurationMs,
+ delayMs = 0,
+ interpolator = Interpolators.EMPHASIZED
+ ),
+ alphaAnimator(
+ from =
+ mCurrentAlphaAtPosition.getOrDefault(
+ key = POSITION_BOTTOM,
+ defaultValue = 1f
+ ),
+ to = 0f,
+ durationMs = mDreamInComplicationsAnimDurationMs,
+ delayMs = 0,
+ positions = POSITION_BOTTOM
+ )
+ .apply {
+ doOnEnd {
+ // The logical end of the animation is once the alpha and blur
+ // animations finish, end the animation so that any listeners are
+ // notified. The Y translation animation is much longer than all of
+ // the other animations due to how the spec is defined, but is not
+ // expected to run to completion.
+ mAnimator?.end()
+ }
+ },
+ alphaAnimator(
+ from =
+ mCurrentAlphaAtPosition.getOrDefault(
+ key = POSITION_TOP,
+ defaultValue = 1f
+ ),
+ to = 0f,
+ durationMs = mDreamInComplicationsAnimDurationMs,
+ delayMs = 0,
+ positions = POSITION_TOP
+ )
+ )
+ doOnEnd {
+ mAnimator = null
+ mOverlayStateController.setExitAnimationsRunning(false)
+ }
+ start()
+ }
+ mOverlayStateController.setExitAnimationsRunning(true)
+ return mAnimator as AnimatorSet
+ }
+
/** Starts the dream content and dream overlay exit animations. */
fun wakeUp(doneCallback: Runnable, executor: DelayableExecutor) {
cancelAnimations()
@@ -182,18 +254,6 @@ constructor(
}
}
- /**
- * Ends the dream content and dream overlay animations, if they're currently running.
- * @see [AnimatorSet.end]
- */
- fun endAnimations() {
- mAnimator =
- mAnimator?.let {
- it.end()
- null
- }
- }
-
private fun blurAnimator(
view: View,
fromBlurRadius: Float,
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index 50cfb6a905c9..4b478cdca9f9 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -23,6 +23,7 @@ import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
import static com.android.systemui.dreams.complication.ComplicationLayoutParams.POSITION_BOTTOM;
import static com.android.systemui.dreams.complication.ComplicationLayoutParams.POSITION_TOP;
+import android.animation.Animator;
import android.content.res.Resources;
import android.os.Handler;
import android.util.MathUtils;
@@ -31,6 +32,7 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
+import com.android.dream.lowlight.LowLightTransitionCoordinator;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.dagger.qualifiers.Main;
@@ -54,11 +56,14 @@ import javax.inject.Named;
* View controller for {@link DreamOverlayContainerView}.
*/
@DreamOverlayComponent.DreamOverlayScope
-public class DreamOverlayContainerViewController extends ViewController<DreamOverlayContainerView> {
+public class DreamOverlayContainerViewController extends
+ ViewController<DreamOverlayContainerView> implements
+ LowLightTransitionCoordinator.LowLightEnterListener {
private final DreamOverlayStatusBarViewController mStatusBarViewController;
private final BlurUtils mBlurUtils;
private final DreamOverlayAnimationsController mDreamOverlayAnimationsController;
private final DreamOverlayStateController mStateController;
+ private final LowLightTransitionCoordinator mLowLightTransitionCoordinator;
private final ComplicationHostViewController mComplicationHostViewController;
@@ -143,19 +148,18 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
};
/**
- * If true, overlay entry animations should be skipped once.
- *
- * This is turned on when exiting low light and should be turned off once the entry animations
- * are skipped once.
+ * If {@code true}, the dream has just transitioned from the low light dream back to the user
+ * dream and we should play an entry animation where the overlay slides in downwards from the
+ * top instead of the typicla slide in upwards from the bottom.
*/
- private boolean mSkipEntryAnimations;
+ private boolean mExitingLowLight;
private final DreamOverlayStateController.Callback
mDreamOverlayStateCallback =
new DreamOverlayStateController.Callback() {
@Override
public void onExitLowLight() {
- mSkipEntryAnimations = true;
+ mExitingLowLight = true;
}
};
@@ -165,6 +169,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
ComplicationHostViewController complicationHostViewController,
@Named(DreamOverlayModule.DREAM_OVERLAY_CONTENT_VIEW) ViewGroup contentView,
DreamOverlayStatusBarViewController statusBarViewController,
+ LowLightTransitionCoordinator lowLightTransitionCoordinator,
BlurUtils blurUtils,
@Main Handler handler,
@Main Resources resources,
@@ -182,6 +187,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
mBlurUtils = blurUtils;
mDreamOverlayAnimationsController = animationsController;
mStateController = stateController;
+ mLowLightTransitionCoordinator = lowLightTransitionCoordinator;
mBouncerlessScrimController = bouncerlessScrimController;
mBouncerlessScrimController.addCallback(mBouncerlessExpansionCallback);
@@ -208,6 +214,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
mStatusBarViewController.init();
mComplicationHostViewController.init();
mDreamOverlayAnimationsController.init(mView);
+ mLowLightTransitionCoordinator.setLowLightEnterListener(this);
}
@Override
@@ -219,14 +226,10 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
// Start dream entry animations. Skip animations for low light clock.
if (!mStateController.isLowLightActive()) {
- mDreamOverlayAnimationsController.startEntryAnimations();
-
- if (mSkipEntryAnimations) {
- // If we're transitioning from the low light dream back to the user dream, skip the
- // overlay animations and show immediately.
- mDreamOverlayAnimationsController.endAnimations();
- mSkipEntryAnimations = false;
- }
+ // If this is transitioning from the low light dream to the user dream, the overlay
+ // should translate in downwards instead of upwards.
+ mDreamOverlayAnimationsController.startEntryAnimations(mExitingLowLight);
+ mExitingLowLight = false;
}
}
@@ -310,4 +313,12 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
mDreamOverlayAnimationsController.wakeUp(onAnimationEnd, callbackExecutor);
}
+
+ @Override
+ public Animator onBeforeEnterLowLight() {
+ // Return the animator so that the transition coordinator waits for the overlay exit
+ // animations to finish before entering low light, as otherwise the default DreamActivity
+ // animation plays immediately and there's no time for this animation to play.
+ return mDreamOverlayAnimationsController.startExitAnimations();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 5aebc3268b90..a0fef758da51 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -16,6 +16,8 @@
package com.android.systemui.dreams;
+import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_WINDOW_TITLE;
+
import android.content.ComponentName;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
@@ -70,6 +72,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
private final ComponentName mLowLightDreamComponent;
private final UiEventLogger mUiEventLogger;
private final WindowManager mWindowManager;
+ private final String mWindowTitle;
// A reference to the {@link Window} used to hold the dream overlay.
private Window mWindow;
@@ -134,7 +137,9 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
UiEventLogger uiEventLogger,
@Nullable @Named(LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT)
ComponentName lowLightDreamComponent,
- DreamOverlayCallbackController dreamOverlayCallbackController) {
+ DreamOverlayCallbackController dreamOverlayCallbackController,
+ @Named(DREAM_OVERLAY_WINDOW_TITLE) String windowTitle) {
+ super(executor);
mContext = context;
mExecutor = executor;
mWindowManager = windowManager;
@@ -144,6 +149,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
mStateController = stateController;
mUiEventLogger = uiEventLogger;
mDreamOverlayCallbackController = dreamOverlayCallbackController;
+ mWindowTitle = windowTitle;
final ViewModelStore viewModelStore = new ViewModelStore();
final Complication.Host host =
@@ -171,48 +177,50 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
@Override
public void onStartDream(@NonNull WindowManager.LayoutParams layoutParams) {
- mExecutor.execute(() -> {
- setCurrentStateLocked(Lifecycle.State.STARTED);
+ setCurrentStateLocked(Lifecycle.State.STARTED);
- mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_ENTER_START);
+ mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_ENTER_START);
- if (mDestroyed) {
- // The task could still be executed after the service has been destroyed. Bail if
- // that is the case.
- return;
- }
+ if (mDestroyed) {
+ // The task could still be executed after the service has been destroyed. Bail if
+ // that is the case.
+ return;
+ }
- if (mStarted) {
- // Reset the current dream overlay before starting a new one. This can happen
- // when two dreams overlap (briefly, for a smoother dream transition) and both
- // dreams are bound to the dream overlay service.
- resetCurrentDreamOverlayLocked();
- }
+ if (mStarted) {
+ // Reset the current dream overlay before starting a new one. This can happen
+ // when two dreams overlap (briefly, for a smoother dream transition) and both
+ // dreams are bound to the dream overlay service.
+ resetCurrentDreamOverlayLocked();
+ }
- mDreamOverlayContainerViewController =
- mDreamOverlayComponent.getDreamOverlayContainerViewController();
- mDreamOverlayTouchMonitor = mDreamOverlayComponent.getDreamOverlayTouchMonitor();
- mDreamOverlayTouchMonitor.init();
-
- mStateController.setShouldShowComplications(shouldShowComplications());
- addOverlayWindowLocked(layoutParams);
- setCurrentStateLocked(Lifecycle.State.RESUMED);
- mStateController.setOverlayActive(true);
- final ComponentName dreamComponent = getDreamComponent();
- mStateController.setLowLightActive(
- dreamComponent != null && dreamComponent.equals(mLowLightDreamComponent));
- mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START);
-
- mDreamOverlayCallbackController.onStartDream();
- mStarted = true;
- });
+ mDreamOverlayContainerViewController =
+ mDreamOverlayComponent.getDreamOverlayContainerViewController();
+ mDreamOverlayTouchMonitor = mDreamOverlayComponent.getDreamOverlayTouchMonitor();
+ mDreamOverlayTouchMonitor.init();
+
+ mStateController.setShouldShowComplications(shouldShowComplications());
+
+ // If we are not able to add the overlay window, reset the overlay.
+ if (!addOverlayWindowLocked(layoutParams)) {
+ resetCurrentDreamOverlayLocked();
+ return;
+ }
+
+ setCurrentStateLocked(Lifecycle.State.RESUMED);
+ mStateController.setOverlayActive(true);
+ final ComponentName dreamComponent = getDreamComponent();
+ mStateController.setLowLightActive(
+ dreamComponent != null && dreamComponent.equals(mLowLightDreamComponent));
+ mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START);
+
+ mDreamOverlayCallbackController.onStartDream();
+ mStarted = true;
}
@Override
public void onEndDream() {
- mExecutor.execute(() -> {
- resetCurrentDreamOverlayLocked();
- });
+ resetCurrentDreamOverlayLocked();
}
private Lifecycle.State getCurrentStateLocked() {
@@ -225,12 +233,10 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
@Override
public void onWakeUp(@NonNull Runnable onCompletedCallback) {
- mExecutor.execute(() -> {
- if (mDreamOverlayContainerViewController != null) {
- mDreamOverlayCallbackController.onWakeUp();
- mDreamOverlayContainerViewController.wakeUp(onCompletedCallback, mExecutor);
- }
- });
+ if (mDreamOverlayContainerViewController != null) {
+ mDreamOverlayCallbackController.onWakeUp();
+ mDreamOverlayContainerViewController.wakeUp(onCompletedCallback, mExecutor);
+ }
}
/**
@@ -241,10 +247,10 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
* @param layoutParams The {@link android.view.WindowManager.LayoutParams} which allow inserting
* into the dream window.
*/
- private void addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) {
+ private boolean addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) {
mWindow = new PhoneWindow(mContext);
// Default to SystemUI name for TalkBack.
- mWindow.setTitle("");
+ mWindow.setTitle(mWindowTitle);
mWindow.setAttributes(layoutParams);
mWindow.setWindowManager(null, layoutParams.token, "DreamOverlay", true);
@@ -266,9 +272,22 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
// risk an IllegalStateException in some cases when setting the container view as the
// window's content view and the container view hasn't been properly removed previously).
removeContainerViewFromParentLocked();
+
mWindow.setContentView(mDreamOverlayContainerViewController.getContainerView());
- mWindowManager.addView(mWindow.getDecorView(), mWindow.getAttributes());
+ // It is possible that a dream's window (and the dream as a whole) is no longer valid by
+ // the time the overlay service processes the dream. This can happen for example if
+ // another dream is started immediately after the existing dream begins. In this case, the
+ // overlay service should identify the situation through the thrown exception and tear down
+ // the overlay.
+ try {
+ mWindowManager.addView(mWindow.getDecorView(), mWindow.getAttributes());
+ return true;
+ } catch (WindowManager.BadTokenException exception) {
+ Log.e(TAG, "Dream activity window invalid: " + layoutParams.packageName,
+ exception);
+ return false;
+ }
}
private void removeContainerViewFromParentLocked() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java
index a2e11b21ea59..aad209090a21 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java
@@ -22,14 +22,18 @@ import static com.android.systemui.dreams.complication.dagger.ComplicationModule
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Debug;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Log;
import android.view.View;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.lifecycle.LifecycleOwner;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.util.ViewController;
+import com.android.systemui.util.settings.SecureSettings;
import java.util.Collection;
import java.util.HashMap;
@@ -54,9 +58,8 @@ public class ComplicationHostViewController extends ViewController<ConstraintLay
private final LifecycleOwner mLifecycleOwner;
private final ComplicationCollectionViewModel mComplicationCollectionViewModel;
private final HashMap<ComplicationId, Complication.ViewHolder> mComplications = new HashMap<>();
-
- // Whether dream entry animations are finished.
- private boolean mEntryAnimationsFinished = false;
+ @VisibleForTesting
+ boolean mIsAnimationEnabled;
@Inject
protected ComplicationHostViewController(
@@ -64,20 +67,17 @@ public class ComplicationHostViewController extends ViewController<ConstraintLay
ComplicationLayoutEngine layoutEngine,
DreamOverlayStateController dreamOverlayStateController,
LifecycleOwner lifecycleOwner,
- @Named(SCOPED_COMPLICATIONS_MODEL) ComplicationCollectionViewModel viewModel) {
+ @Named(SCOPED_COMPLICATIONS_MODEL) ComplicationCollectionViewModel viewModel,
+ SecureSettings secureSettings) {
super(view);
mLayoutEngine = layoutEngine;
mLifecycleOwner = lifecycleOwner;
mComplicationCollectionViewModel = viewModel;
mDreamOverlayStateController = dreamOverlayStateController;
- mDreamOverlayStateController.addCallback(new DreamOverlayStateController.Callback() {
- @Override
- public void onStateChanged() {
- mEntryAnimationsFinished =
- mDreamOverlayStateController.areEntryAnimationsFinished();
- }
- });
+ // Whether animations are enabled.
+ mIsAnimationEnabled = secureSettings.getFloatForUser(
+ Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f, UserHandle.USER_CURRENT) != 0.0f;
}
@Override
@@ -148,7 +148,8 @@ public class ComplicationHostViewController extends ViewController<ConstraintLay
// Complications to be added before dream entry animations are finished are set
// to invisible and are animated in.
- if (!mEntryAnimationsFinished) {
+ if (!mDreamOverlayStateController.areEntryAnimationsFinished()
+ && mIsAnimationEnabled) {
view.setVisibility(View.INVISIBLE);
}
mComplications.put(id, viewHolder);
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
index e39073bb6711..ff1f31245570 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
@@ -28,6 +28,8 @@ import android.widget.FrameLayout;
import com.android.systemui.CoreStartable;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.BcSmartspaceDataPlugin;
import com.android.systemui.shared.condition.Monitor;
import com.android.systemui.util.condition.ConditionalCoreStartable;
@@ -68,6 +70,7 @@ public class SmartSpaceComplication implements Complication {
private final DreamSmartspaceController mSmartSpaceController;
private final DreamOverlayStateController mDreamOverlayStateController;
private final SmartSpaceComplication mComplication;
+ private final FeatureFlags mFeatureFlags;
private final BcSmartspaceDataPlugin.SmartspaceTargetListener mSmartspaceListener =
new BcSmartspaceDataPlugin.SmartspaceTargetListener() {
@@ -85,15 +88,21 @@ public class SmartSpaceComplication implements Complication {
DreamOverlayStateController dreamOverlayStateController,
SmartSpaceComplication smartSpaceComplication,
DreamSmartspaceController smartSpaceController,
- @Named(DREAM_PRETEXT_MONITOR) Monitor monitor) {
+ @Named(DREAM_PRETEXT_MONITOR) Monitor monitor,
+ FeatureFlags featureFlags) {
super(monitor);
mDreamOverlayStateController = dreamOverlayStateController;
mComplication = smartSpaceComplication;
mSmartSpaceController = smartSpaceController;
+ mFeatureFlags = featureFlags;
}
@Override
public void onStart() {
+ if (mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)) {
+ return;
+ }
+
mDreamOverlayStateController.addCallback(new DreamOverlayStateController.Callback() {
@Override
public void onStateChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index 88c02b8aa790..93a57543ec05 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -23,13 +23,14 @@ import android.content.res.Resources;
import com.android.dream.lowlight.dagger.LowLightDreamModule;
import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
import com.android.systemui.dreams.DreamOverlayService;
import com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule;
import com.android.systemui.dreams.touch.scrim.dagger.ScrimModule;
-import com.android.systemui.process.condition.UserProcessCondition;
+import com.android.systemui.process.condition.SystemProcessCondition;
import com.android.systemui.shared.condition.Condition;
import com.android.systemui.shared.condition.Monitor;
@@ -63,6 +64,8 @@ public interface DreamModule {
String DREAM_SUPPORTED = "dream_supported";
String DREAM_PRETEXT_CONDITIONS = "dream_pretext_conditions";
String DREAM_PRETEXT_MONITOR = "dream_prtext_monitor";
+ String DREAM_OVERLAY_WINDOW_TITLE = "dream_overlay_window_title";
+
/**
* Provides the dream component
@@ -126,7 +129,7 @@ public interface DreamModule {
@Binds
@IntoSet
@Named(DREAM_PRETEXT_CONDITIONS)
- Condition bindsUserProcessCondition(UserProcessCondition condition);
+ Condition bindSystemProcessCondition(SystemProcessCondition condition);
/** */
@Provides
@@ -136,4 +139,11 @@ public interface DreamModule {
@Named(DREAM_PRETEXT_CONDITIONS) Set<Condition> pretextConditions) {
return new Monitor(executor, pretextConditions);
}
+
+ /** */
+ @Provides
+ @Named(DREAM_OVERLAY_WINDOW_TITLE)
+ static String providesDreamOverlayWindowTitle(@Main Resources resources) {
+ return resources.getString(R.string.app_label);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
index 73c2289ad6bd..a7b3bbcbc37b 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
@@ -254,7 +254,10 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
mCurrentScrimController = mScrimManager.getCurrentController();
session.registerCallback(() -> {
- mVelocityTracker.recycle();
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
mScrimManager.removeCallback(mScrimManagerCallback);
mCapture = null;
mNotificationShadeWindowController.setForcePluginOpen(false, this);
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java
index f5bbba780b27..776b7bd080d0 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java
@@ -34,7 +34,7 @@ public class BouncerScrimController implements ScrimController {
@Override
public void show() {
- mStatusBarKeyguardViewManager.showBouncer(false);
+ mStatusBarKeyguardViewManager.showPrimaryBouncer(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ConditionalRestarter.kt b/packages/SystemUI/src/com/android/systemui/flags/ConditionalRestarter.kt
new file mode 100644
index 000000000000..b20e33a63776
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/ConditionalRestarter.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import android.util.Log
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import java.util.concurrent.TimeUnit
+import javax.inject.Inject
+import javax.inject.Named
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+/** Restarts the process after all passed in [Condition]s are true. */
+class ConditionalRestarter
+@Inject
+constructor(
+ private val systemExitRestarter: SystemExitRestarter,
+ private val conditions: Set<@JvmSuppressWildcards Condition>,
+ @Named(RESTART_DELAY) private val restartDelaySec: Long,
+ @Application private val applicationScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+) : Restarter {
+
+ private var restartJob: Job? = null
+ private var pendingReason = ""
+ private var androidRestartRequested = false
+
+ override fun restartSystemUI(reason: String) {
+ Log.d(FeatureFlagsDebug.TAG, "SystemUI Restart requested. Restarting when idle.")
+ scheduleRestart(reason)
+ }
+
+ override fun restartAndroid(reason: String) {
+ Log.d(FeatureFlagsDebug.TAG, "Android Restart requested. Restarting when idle.")
+ androidRestartRequested = true
+ scheduleRestart(reason)
+ }
+
+ private fun scheduleRestart(reason: String = "") {
+ pendingReason = if (reason.isEmpty()) pendingReason else reason
+
+ if (conditions.all { c -> c.canRestartNow(this::scheduleRestart) }) {
+ if (restartJob == null) {
+ restartJob =
+ applicationScope.launch(backgroundDispatcher) {
+ delay(TimeUnit.SECONDS.toMillis(restartDelaySec))
+ restartNow()
+ }
+ }
+ } else {
+ restartJob?.cancel()
+ restartJob = null
+ }
+ }
+
+ private fun restartNow() {
+ if (androidRestartRequested) {
+ systemExitRestarter.restartAndroid(pendingReason)
+ } else {
+ systemExitRestarter.restartSystemUI(pendingReason)
+ }
+ }
+
+ interface Condition {
+ /**
+ * Should return true if the system is ready to restart.
+ *
+ * A call to this function means that we want to restart and are waiting for this condition
+ * to return true.
+ *
+ * retryFn should be cached if it is _not_ ready to restart, and later called when it _is_
+ * ready to restart. At that point, this method will be called again to verify that the
+ * system is ready.
+ *
+ * Multiple calls to an instance of this method may happen for a single restart attempt if
+ * multiple [Condition]s are being checked. If any one [Condition] returns false, all the
+ * [Condition]s will need to be rechecked on the next restart attempt.
+ */
+ fun canRestartNow(retryFn: () -> Unit): Boolean
+ }
+
+ companion object {
+ const val RESTART_DELAY = "restarter_restart_delay"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugRestarter.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugRestarter.kt
deleted file mode 100644
index a6956a443e46..000000000000
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugRestarter.kt
+++ /dev/null
@@ -1,70 +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.systemui.flags
-
-import android.util.Log
-import com.android.systemui.keyguard.WakefulnessLifecycle
-import javax.inject.Inject
-
-/** Restarts SystemUI when the screen is locked. */
-class FeatureFlagsDebugRestarter
-@Inject
-constructor(
- private val wakefulnessLifecycle: WakefulnessLifecycle,
- private val systemExitRestarter: SystemExitRestarter,
-) : Restarter {
-
- private var androidRestartRequested = false
- private var pendingReason = ""
-
- val observer =
- object : WakefulnessLifecycle.Observer {
- override fun onFinishedGoingToSleep() {
- Log.d(FeatureFlagsDebug.TAG, "Restarting due to systemui flag change")
- restartNow()
- }
- }
-
- override fun restartSystemUI(reason: String) {
- Log.d(FeatureFlagsDebug.TAG, "SystemUI Restart requested. Restarting on next screen off.")
- Log.i(FeatureFlagsDebug.TAG, reason)
- scheduleRestart(reason)
- }
-
- override fun restartAndroid(reason: String) {
- Log.d(FeatureFlagsDebug.TAG, "Android Restart requested. Restarting on next screen off.")
- androidRestartRequested = true
- scheduleRestart(reason)
- }
-
- fun scheduleRestart(reason: String) {
- pendingReason = reason
- if (wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_ASLEEP) {
- restartNow()
- } else {
- wakefulnessLifecycle.addObserver(observer)
- }
- }
-
- private fun restartNow() {
- if (androidRestartRequested) {
- systemExitRestarter.restartAndroid(pendingReason)
- } else {
- systemExitRestarter.restartSystemUI(pendingReason)
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseRestarter.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseRestarter.kt
deleted file mode 100644
index c08266caf147..000000000000
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseRestarter.kt
+++ /dev/null
@@ -1,101 +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.systemui.flags
-
-import android.util.Log
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.keyguard.WakefulnessLifecycle
-import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP
-import com.android.systemui.statusbar.policy.BatteryController
-import com.android.systemui.util.concurrency.DelayableExecutor
-import java.util.concurrent.TimeUnit
-import javax.inject.Inject
-
-/** Restarts SystemUI when the device appears idle. */
-class FeatureFlagsReleaseRestarter
-@Inject
-constructor(
- private val wakefulnessLifecycle: WakefulnessLifecycle,
- private val batteryController: BatteryController,
- @Background private val bgExecutor: DelayableExecutor,
- private val systemExitRestarter: SystemExitRestarter
-) : Restarter {
- var listenersAdded = false
- var pendingRestart: Runnable? = null
- private var pendingReason = ""
- var androidRestartRequested = false
-
- val observer =
- object : WakefulnessLifecycle.Observer {
- override fun onFinishedGoingToSleep() {
- scheduleRestart(pendingReason)
- }
- }
-
- val batteryCallback =
- object : BatteryController.BatteryStateChangeCallback {
- override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
- scheduleRestart(pendingReason)
- }
- }
-
- override fun restartSystemUI(reason: String) {
- Log.d(
- FeatureFlagsDebug.TAG,
- "SystemUI Restart requested. Restarting when plugged in and idle."
- )
- scheduleRestart(reason)
- }
-
- override fun restartAndroid(reason: String) {
- Log.d(
- FeatureFlagsDebug.TAG,
- "Android Restart requested. Restarting when plugged in and idle."
- )
- androidRestartRequested = true
- scheduleRestart(reason)
- }
-
- private fun scheduleRestart(reason: String) {
- // Don't bother adding listeners twice.
- pendingReason = reason
- if (!listenersAdded) {
- listenersAdded = true
- wakefulnessLifecycle.addObserver(observer)
- batteryController.addCallback(batteryCallback)
- }
- if (
- wakefulnessLifecycle.wakefulness == WAKEFULNESS_ASLEEP && batteryController.isPluggedIn
- ) {
- if (pendingRestart == null) {
- pendingRestart = bgExecutor.executeDelayed(this::restartNow, 30L, TimeUnit.SECONDS)
- }
- } else if (pendingRestart != null) {
- pendingRestart?.run()
- pendingRestart = null
- }
- }
-
- private fun restartNow() {
- Log.d(FeatureFlagsRelease.TAG, "Restarting due to systemui flag change")
- if (androidRestartRequested) {
- systemExitRestarter.restartAndroid(pendingReason)
- } else {
- systemExitRestarter.restartSystemUI(pendingReason)
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 9fe1739fab0f..8585335eb7fa 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -62,7 +62,7 @@ object Flags {
val FSI_REQUIRES_KEYGUARD = releasedFlag(110, "fsi_requires_keyguard")
// TODO(b/259130119): Tracking Bug
- val FSI_ON_DND_UPDATE = unreleasedFlag(259130119, "fsi_on_dnd_update", teamfood = true)
+ val FSI_ON_DND_UPDATE = releasedFlag(259130119, "fsi_on_dnd_update")
// TODO(b/265804648): Tracking Bug
@JvmField val DISABLE_FSI = unreleasedFlag(265804648, "disable_fsi")
@@ -74,8 +74,12 @@ object Flags {
val NOTIFICATION_MEMORY_MONITOR_ENABLED =
releasedFlag(112, "notification_memory_monitor_enabled")
+ /**
+ * This flag is server-controlled and should stay as [unreleasedFlag] since we never want to
+ * enable it on release builds.
+ */
val NOTIFICATION_MEMORY_LOGGING_ENABLED =
- unreleasedFlag(119, "notification_memory_logging_enabled", teamfood = true)
+ unreleasedFlag(119, "notification_memory_logging_enabled")
// TODO(b/254512731): Tracking Bug
@JvmField val NOTIFICATION_DISMISSAL_FADE = releasedFlag(113, "notification_dismissal_fade")
@@ -109,6 +113,13 @@ object Flags {
@JvmField
val NOTIFICATION_ANIMATE_BIG_PICTURE = unreleasedFlag(120, "notification_animate_big_picture")
+ @JvmField
+ val ANIMATED_NOTIFICATION_SHADE_INSETS =
+ unreleasedFlag(270682168, "animated_notification_shade_insets", teamfood = true)
+
+ // TODO(b/268005230): Tracking Bug
+ @JvmField val SENSITIVE_REVEAL_ANIM = unreleasedFlag(268005230, "sensitive_reveal_anim")
+
// 200 - keyguard/lockscreen
// ** Flag retired **
// public static final BooleanFlag KEYGUARD_LAYOUT =
@@ -132,7 +143,7 @@ object Flags {
* the digits when the clock moves.
*/
@JvmField
- val STEP_CLOCK_ANIMATION = unreleasedFlag(212, "step_clock_animation", teamfood = true)
+ val STEP_CLOCK_ANIMATION = releasedFlag(212, "step_clock_animation")
/**
* Migration from the legacy isDozing/dozeAmount paths to the new KeyguardTransitionRepository
@@ -157,12 +168,6 @@ object Flags {
val CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES =
unreleasedFlag(216, "customizable_lock_screen_quick_affordances", teamfood = true)
- /** Shows chipbar UI whenever the device is unlocked by ActiveUnlock (watch). */
- // TODO(b/256513609): Tracking Bug
- @JvmField
- val ACTIVE_UNLOCK_CHIPBAR =
- resourceBooleanFlag(217, R.bool.flag_active_unlock_chipbar, "active_unlock_chipbar")
-
/**
* Migrates control of the LightRevealScrim's reveal effect and amount from legacy code to the
* new KeyguardTransitionRepository.
@@ -189,10 +194,6 @@ object Flags {
@JvmField
val REVAMPED_WALLPAPER_UI = unreleasedFlag(222, "revamped_wallpaper_ui", teamfood = true)
- /** A different path for unocclusion transitions back to keyguard */
- // TODO(b/262859270): Tracking Bug
- @JvmField val UNOCCLUSION_TRANSITION = releasedFlag(223, "unocclusion_transition")
-
// flag for controlling auto pin confirmation and material u shapes in bouncer
@JvmField
val AUTO_PIN_CONFIRMATION =
@@ -220,6 +221,11 @@ object Flags {
teamfood = true,
)
+ /** Whether to inflate the bouncer view on a background thread. */
+ // TODO(b/272091103): Tracking Bug
+ @JvmField
+ val ASYNC_INFLATE_BOUNCER = unreleasedFlag(229, "async_inflate_bouncer", teamfood = true)
+
// 300 - power menu
// TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
@@ -235,10 +241,12 @@ object Flags {
val SMARTSPACE_DATE_WEATHER_DECOUPLED =
sysPropBooleanFlag(403, "persist.sysui.ss.dw_decoupled", default = false)
+ // TODO(b/270223352): Tracking Bug
+ @JvmField
+ val HIDE_SMARTSPACE_ON_DREAM_OVERLAY = unreleasedFlag(404, "hide_smartspace_on_dream_overlay")
+
// 500 - quick settings
- // TODO(b/254512321): Tracking Bug
- @JvmField val COMBINED_QS_HEADERS = releasedFlag(501, "combined_qs_headers")
val PEOPLE_TILE = resourceBooleanFlag(502, R.bool.flag_conversations, "people_tile")
@JvmField
@@ -249,6 +257,9 @@ object Flags {
"qs_user_detail_shortcut"
)
+ @JvmField
+ val QS_PIPELINE_NEW_HOST = unreleasedFlag(504, "qs_pipeline_new_host", teamfood = false)
+
// TODO(b/254512383): Tracking Bug
@JvmField
val FULL_SCREEN_USER_SWITCHER =
@@ -268,6 +279,11 @@ object Flags {
@JvmField
val ENABLE_FONT_SCALING_TILE = unreleasedFlag(509, "enable_font_scaling_tile", teamfood = false)
+ /** Enables new QS Edit Mode visual refresh */
+ // TODO(b/269787742): Tracking Bug
+ @JvmField
+ val ENABLE_NEW_QS_EDIT_MODE = unreleasedFlag(510, "enable_new_qs_edit_mode", teamfood = false)
+
// 600- status bar
// TODO(b/256614753): Tracking Bug
@@ -294,6 +310,10 @@ object Flags {
val NEW_STATUS_BAR_ICONS_DEBUG_COLORING =
unreleasedFlag(611, "new_status_bar_icons_debug_coloring")
+ // TODO(b/265892345): Tracking Bug
+ val PLUG_IN_STATUS_BAR_CHIP =
+ unreleasedFlag(265892345, "plug_in_status_bar_chip", teamfood = true)
+
// 700 - dialer/calls
// TODO(b/254512734): Tracking Bug
val ONGOING_CALL_STATUS_BAR_CHIP = releasedFlag(700, "ongoing_call_status_bar_chip")
@@ -349,7 +369,7 @@ object Flags {
val MEDIA_TTT_RECEIVER_SUCCESS_RIPPLE = releasedFlag(910, "media_ttt_receiver_success_ripple")
// TODO(b/263512203): Tracking Bug
- val MEDIA_EXPLICIT_INDICATOR = unreleasedFlag(911, "media_explicit_indicator", teamfood = true)
+ val MEDIA_EXPLICIT_INDICATOR = unreleasedFlag(911, "media_explicit_indicator")
// TODO(b/265813373): Tracking Bug
val MEDIA_TAP_TO_TRANSFER_DISMISS_GESTURE = releasedFlag(912, "media_ttt_dismiss_gesture")
@@ -367,15 +387,27 @@ object Flags {
// TODO(b/267166152) : Tracking Bug
val MEDIA_RETAIN_RECOMMENDATIONS = unreleasedFlag(916, "media_retain_recommendations")
+ // TODO(b/270437894): Tracking Bug
+ val MEDIA_REMOTE_RESUME = unreleasedFlag(917, "media_remote_resume")
+
// 1000 - dock
val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging")
// TODO(b/254512758): Tracking Bug
@JvmField val ROUNDED_BOX_RIPPLE = releasedFlag(1002, "rounded_box_ripple")
+ // TODO(b/270882464): Tracking Bug
+ val ENABLE_DOCK_SETUP_V2 = unreleasedFlag(1005, "enable_dock_setup_v2", teamfood = true)
+
// TODO(b/265045965): Tracking Bug
val SHOW_LOWLIGHT_ON_DIRECT_BOOT = releasedFlag(1003, "show_lowlight_on_direct_boot")
+ @JvmField
+ // TODO(b/271428141): Tracking Bug
+ val ENABLE_LOW_LIGHT_CLOCK_UNDOCKED = unreleasedFlag(
+ 1004,
+ "enable_low_light_clock_undocked", teamfood = true)
+
// 1100 - windowing
@Keep
@JvmField
@@ -429,7 +461,9 @@ object Flags {
)
// TODO(b/256873975): Tracking Bug
- @JvmField @Keep val WM_BUBBLE_BAR = unreleasedFlag(1111, "wm_bubble_bar")
+ @JvmField
+ @Keep
+ val WM_BUBBLE_BAR = sysPropBooleanFlag(1111, "persist.wm.debug.bubble_bar", default = false)
// TODO(b/260271148): Tracking bug
@Keep
@@ -452,13 +486,20 @@ object Flags {
@Keep
@JvmField
val ENABLE_PIP_SIZE_LARGE_SCREEN =
- sysPropBooleanFlag(1114, "persist.wm.debug.enable_pip_size_large_screen", default = false)
+ sysPropBooleanFlag(1114, "persist.wm.debug.enable_pip_size_large_screen", default = true)
// TODO(b/265998256): Tracking bug
@Keep
@JvmField
val ENABLE_PIP_APP_ICON_OVERLAY =
- sysPropBooleanFlag(1115, "persist.wm.debug.enable_pip_app_icon_overlay", default = false)
+ sysPropBooleanFlag(1115, "persist.wm.debug.enable_pip_app_icon_overlay", default = true)
+
+ // TODO(b/272110828): Tracking bug
+ @Keep
+ @JvmField
+ val ENABLE_MOVE_FLOATING_WINDOW_IN_TABLETOP =
+ sysPropBooleanFlag(
+ 1116, "persist.wm.debug.enable_move_floating_window_in_tabletop", default = false)
// 1200 - predictive back
@Keep
@@ -535,7 +576,7 @@ object Flags {
// 1500 - chooser aka sharesheet
// TODO(b/254512507): Tracking Bug
- val CHOOSER_UNBUNDLED = releasedFlag(1500, "chooser_unbundled")
+ val CHOOSER_UNBUNDLED = unreleasedFlag(1500, "chooser_unbundled")
// TODO(b/266983432) Tracking Bug
val SHARESHEET_CUSTOM_ACTIONS =
@@ -568,7 +609,7 @@ object Flags {
@JvmField
val LEAVE_SHADE_OPEN_FOR_BUGREPORT = releasedFlag(1800, "leave_shade_open_for_bugreport")
// TODO(b/265944639): Tracking Bug
- @JvmField val DUAL_SHADE = releasedFlag(1801, "dual_shade")
+ @JvmField val DUAL_SHADE = unreleasedFlag(1801, "dual_shade")
// 1900
@JvmField val NOTE_TASKS = unreleasedFlag(1900, "keycode_flag")
@@ -600,7 +641,8 @@ object Flags {
@JvmField val UDFPS_ELLIPSE_DETECTION = unreleasedFlag(2202, "udfps_ellipse_detection")
// 2300 - stylus
- @JvmField val TRACK_STYLUS_EVER_USED = releasedFlag(2300, "track_stylus_ever_used")
+ @JvmField
+ val TRACK_STYLUS_EVER_USED = releasedFlag(2300, "track_stylus_ever_used")
@JvmField val ENABLE_STYLUS_CHARGING_UI = unreleasedFlag(2301, "enable_stylus_charging_ui")
@JvmField
val ENABLE_USI_BATTERY_NOTIFICATIONS = unreleasedFlag(2302, "enable_usi_battery_notifications")
@@ -622,11 +664,6 @@ object Flags {
@JvmField
val OUTPUT_SWITCHER_DEVICE_STATUS = unreleasedFlag(2502, "output_switcher_device_status")
- // TODO(b/20911786): Tracking Bug
- @JvmField
- val OUTPUT_SWITCHER_SHOW_API_ENABLED =
- releasedFlag(2503, "output_switcher_show_api_enabled", teamfood = true)
-
// 2700 - unfold transitions
// TODO(b/265764985): Tracking Bug
@Keep
@@ -644,4 +681,9 @@ object Flags {
// TODO(b/259428678): Tracking Bug
@JvmField
val KEYBOARD_BACKLIGHT_INDICATOR = unreleasedFlag(2601, "keyboard_backlight_indicator")
+
+ // TODO(b/272036292): Tracking Bug
+ @JvmField
+ val LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION =
+ unreleasedFlag(2602, "large_shade_granular_alpha_interpolation", teamfood = true)
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt
index 0054d266c283..3c5012559a89 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt
@@ -15,6 +15,7 @@
*/
package com.android.systemui.flags
+import dagger.Binds
import dagger.Module
import dagger.Provides
import javax.inject.Named
@@ -22,6 +23,8 @@ import javax.inject.Named
/** Module containing shared code for all FeatureFlag implementations. */
@Module
interface FlagsCommonModule {
+ @Binds fun bindsRestarter(impl: ConditionalRestarter): Restarter
+
companion object {
const val ALL_FLAGS = "all_flags"
diff --git a/packages/SystemUI/src/com/android/systemui/flags/PluggedInCondition.kt b/packages/SystemUI/src/com/android/systemui/flags/PluggedInCondition.kt
new file mode 100644
index 000000000000..3120638cb17f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/PluggedInCondition.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import com.android.systemui.statusbar.policy.BatteryController
+import javax.inject.Inject
+
+/** Returns true when the device is plugged in. */
+class PluggedInCondition
+@Inject
+constructor(
+ private val batteryController: BatteryController,
+) : ConditionalRestarter.Condition {
+
+ var listenersAdded = false
+ var retryFn: (() -> Unit)? = null
+
+ val batteryCallback =
+ object : BatteryController.BatteryStateChangeCallback {
+ override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
+ retryFn?.invoke()
+ }
+ }
+
+ override fun canRestartNow(retryFn: () -> Unit): Boolean {
+ if (!listenersAdded) {
+ listenersAdded = true
+ batteryController.addCallback(batteryCallback)
+ }
+
+ this.retryFn = retryFn
+
+ return batteryController.isPluggedIn
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ScreenIdleCondition.kt b/packages/SystemUI/src/com/android/systemui/flags/ScreenIdleCondition.kt
new file mode 100644
index 000000000000..49e61afbdcd6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/ScreenIdleCondition.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import javax.inject.Inject
+
+/** Returns true when the device is "asleep" as defined by the [WakefullnessLifecycle]. */
+class ScreenIdleCondition
+@Inject
+constructor(
+ private val wakefulnessLifecycle: WakefulnessLifecycle,
+) : ConditionalRestarter.Condition {
+
+ var listenersAdded = false
+ var retryFn: (() -> Unit)? = null
+
+ val observer =
+ object : WakefulnessLifecycle.Observer {
+ override fun onFinishedGoingToSleep() {
+ retryFn?.invoke()
+ }
+ }
+
+ override fun canRestartNow(retryFn: () -> Unit): Boolean {
+ if (!listenersAdded) {
+ listenersAdded = true
+ wakefulnessLifecycle.addObserver(observer)
+ }
+
+ this.retryFn = retryFn
+
+ return wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_ASLEEP
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
index 7acd3f3447dd..9b748d0a0eb2 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
@@ -57,6 +57,7 @@ class ServerFlagReaderImpl @Inject constructor(
override fun onPropertiesChanged(properties: DeviceConfig.Properties) {
if (isTestHarness) {
Log.w(TAG, "Ignore server flag changes in Test Harness mode.")
+ return
}
if (properties.namespace != namespace) {
return
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index e80e71c7b599..03b45b512010 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -2054,6 +2054,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
|| Intent.ACTION_SCREEN_OFF.equals(action)) {
String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
if (!SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS.equals(reason)) {
+ // These broadcasts are usually received when locking the device, swiping up to
+ // home (which collapses the shade), etc. In those cases, we usually don't want
+ // to animate this dialog back into the view, so we disable the exit animations.
+ mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISMISS, reason));
}
} else if (TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
index e9b8908214fc..496c64e1120e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
@@ -17,6 +17,14 @@
package com.android.systemui.keyboard
+import com.android.systemui.keyboard.data.repository.KeyboardRepository
+import com.android.systemui.keyboard.data.repository.KeyboardRepositoryImpl
+import dagger.Binds
import dagger.Module
-@Module abstract class KeyboardModule
+@Module
+abstract class KeyboardModule {
+
+ @Binds
+ abstract fun bindKeyboardRepository(repository: KeyboardRepositoryImpl): KeyboardRepository
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt
index b0f9c4edb073..d078688e5944 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt
@@ -21,6 +21,7 @@ import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.keyboard.backlight.ui.KeyboardBacklightDialogCoordinator
import javax.inject.Inject
/** A [CoreStartable] that launches components interested in physical keyboard interaction. */
@@ -28,11 +29,12 @@ import javax.inject.Inject
class PhysicalKeyboardCoreStartable
@Inject
constructor(
+ private val keyboardBacklightDialogCoordinator: KeyboardBacklightDialogCoordinator,
private val featureFlags: FeatureFlags,
) : CoreStartable {
override fun start() {
if (featureFlags.isEnabled(Flags.KEYBOARD_BACKLIGHT_INDICATOR)) {
- // TODO(b/268645743) start listening for keyboard backlight brightness
+ keyboardBacklightDialogCoordinator.startListening()
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt
new file mode 100644
index 000000000000..65e70b319923
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyboard.backlight.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyboard.data.repository.KeyboardRepository
+import com.android.systemui.keyboard.shared.model.BacklightModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+
+/** Allows listening to changes to keyboard backlight level */
+@SysUISingleton
+class KeyboardBacklightInteractor
+@Inject
+constructor(
+ private val keyboardRepository: KeyboardRepository,
+) {
+
+ /** Emits current backlight level as [BacklightModel] or null if keyboard is not connected */
+ val backlight: Flow<BacklightModel?> =
+ keyboardRepository.keyboardConnected.flatMapLatest { connected ->
+ if (connected) keyboardRepository.backlight else flowOf(null)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/KeyboardBacklightDialogCoordinator.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/KeyboardBacklightDialogCoordinator.kt
new file mode 100644
index 000000000000..5e806b612805
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/KeyboardBacklightDialogCoordinator.kt
@@ -0,0 +1,66 @@
+/*
+ * 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.keyboard.backlight.ui
+
+import android.content.Context
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyboard.backlight.ui.view.KeyboardBacklightDialog
+import com.android.systemui.keyboard.backlight.ui.viewmodel.BacklightDialogViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+/**
+ * Based on the state produced from [BacklightDialogViewModel] shows or hides keyboard backlight
+ * indicator
+ */
+@SysUISingleton
+class KeyboardBacklightDialogCoordinator
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ private val context: Context,
+ private val viewModel: BacklightDialogViewModel,
+) {
+
+ var dialog: KeyboardBacklightDialog? = null
+
+ fun startListening() {
+ applicationScope.launch {
+ viewModel.dialogContent.collect { dialogViewModel ->
+ if (dialogViewModel != null) {
+ if (dialog == null) {
+ dialog =
+ KeyboardBacklightDialog(
+ context,
+ initialCurrentLevel = dialogViewModel.currentValue,
+ initialMaxLevel = dialogViewModel.maxValue
+ )
+ dialog?.show()
+ } else {
+ dialog?.updateState(dialogViewModel.currentValue, dialogViewModel.maxValue)
+ }
+ } else {
+ dialog?.dismiss()
+ dialog = null
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt
new file mode 100644
index 000000000000..a173f8b914db
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt
@@ -0,0 +1,276 @@
+/*
+ * 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.keyboard.backlight.ui.view
+
+import android.annotation.ColorInt
+import android.app.Dialog
+import android.content.Context
+import android.graphics.drawable.ShapeDrawable
+import android.graphics.drawable.shapes.RoundRectShape
+import android.os.Bundle
+import android.view.Gravity
+import android.view.Window
+import android.view.WindowManager
+import android.widget.FrameLayout
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.LinearLayout.LayoutParams
+import android.widget.LinearLayout.LayoutParams.WRAP_CONTENT
+import com.android.systemui.R
+import com.android.systemui.util.children
+
+class KeyboardBacklightDialog(
+ context: Context,
+ initialCurrentLevel: Int,
+ initialMaxLevel: Int,
+) : Dialog(context) {
+
+ private data class RootProperties(
+ val cornerRadius: Float,
+ val verticalPadding: Int,
+ val horizontalPadding: Int,
+ )
+
+ private data class BacklightIconProperties(
+ val width: Int,
+ val height: Int,
+ val leftMargin: Int,
+ )
+
+ private data class StepViewProperties(
+ val width: Int,
+ val height: Int,
+ val horizontalMargin: Int,
+ val smallRadius: Float,
+ val largeRadius: Float,
+ )
+
+ private var currentLevel: Int = 0
+ private var maxLevel: Int = 0
+
+ private lateinit var rootView: LinearLayout
+
+ private var dialogBottomMargin = 208
+ private lateinit var rootProperties: RootProperties
+ private lateinit var iconProperties: BacklightIconProperties
+ private lateinit var stepProperties: StepViewProperties
+ @ColorInt var filledRectangleColor: Int = 0
+ @ColorInt var emptyRectangleColor: Int = 0
+ @ColorInt var backgroundColor: Int = 0
+
+ init {
+ currentLevel = initialCurrentLevel
+ maxLevel = initialMaxLevel
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ setUpWindowProperties(this)
+ setWindowTitle()
+ updateResources()
+ rootView = buildRootView()
+ setContentView(rootView)
+ super.onCreate(savedInstanceState)
+ updateState(currentLevel, maxLevel, forceRefresh = true)
+ }
+
+ private fun updateResources() {
+ context.resources.apply {
+ filledRectangleColor = getColor(R.color.backlight_indicator_step_filled)
+ emptyRectangleColor = getColor(R.color.backlight_indicator_step_empty)
+ backgroundColor = getColor(R.color.backlight_indicator_background)
+ rootProperties =
+ RootProperties(
+ cornerRadius =
+ getDimensionPixelSize(R.dimen.backlight_indicator_root_corner_radius)
+ .toFloat(),
+ verticalPadding =
+ getDimensionPixelSize(R.dimen.backlight_indicator_root_vertical_padding),
+ horizontalPadding =
+ getDimensionPixelSize(R.dimen.backlight_indicator_root_horizontal_padding)
+ )
+ iconProperties =
+ BacklightIconProperties(
+ width = getDimensionPixelSize(R.dimen.backlight_indicator_icon_width),
+ height = getDimensionPixelSize(R.dimen.backlight_indicator_icon_height),
+ leftMargin =
+ getDimensionPixelSize(R.dimen.backlight_indicator_icon_left_margin),
+ )
+ stepProperties =
+ StepViewProperties(
+ width = getDimensionPixelSize(R.dimen.backlight_indicator_step_width),
+ height = getDimensionPixelSize(R.dimen.backlight_indicator_step_height),
+ horizontalMargin =
+ getDimensionPixelSize(R.dimen.backlight_indicator_step_horizontal_margin),
+ smallRadius =
+ getDimensionPixelSize(R.dimen.backlight_indicator_step_small_radius)
+ .toFloat(),
+ largeRadius =
+ getDimensionPixelSize(R.dimen.backlight_indicator_step_large_radius)
+ .toFloat(),
+ )
+ }
+ }
+
+ fun updateState(current: Int, max: Int, forceRefresh: Boolean = false) {
+ if (maxLevel != max || forceRefresh) {
+ maxLevel = max
+ rootView.removeAllViews()
+ buildStepViews().forEach { rootView.addView(it) }
+ }
+ currentLevel = current
+ updateLevel()
+ }
+
+ private fun updateLevel() {
+ rootView.children.forEachIndexed(
+ action = { index, v ->
+ val drawable = v.background as ShapeDrawable
+ if (index <= currentLevel) {
+ updateColor(drawable, filledRectangleColor)
+ } else {
+ updateColor(drawable, emptyRectangleColor)
+ }
+ }
+ )
+ }
+
+ private fun updateColor(drawable: ShapeDrawable, @ColorInt color: Int) {
+ if (drawable.paint.color != color) {
+ drawable.paint.color = color
+ drawable.invalidateSelf()
+ }
+ }
+
+ private fun buildRootView(): LinearLayout {
+ val linearLayout =
+ LinearLayout(context).apply {
+ orientation = LinearLayout.HORIZONTAL
+ layoutParams = LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
+ setPadding(
+ /* left= */ rootProperties.horizontalPadding,
+ /* top= */ rootProperties.verticalPadding,
+ /* right= */ rootProperties.horizontalPadding,
+ /* bottom= */ rootProperties.verticalPadding
+ )
+ }
+ val drawable =
+ ShapeDrawable(
+ RoundRectShape(
+ /* outerRadii= */ FloatArray(8) { rootProperties.cornerRadius },
+ /* inset= */ null,
+ /* innerRadii= */ null
+ )
+ )
+ drawable.paint.color = backgroundColor
+ linearLayout.background = drawable
+ return linearLayout
+ }
+
+ private fun buildStepViews(): List<FrameLayout> {
+ val stepViews = (0..maxLevel).map { i -> createStepViewAt(i) }
+ stepViews[0].addView(createBacklightIconView())
+ return stepViews
+ }
+
+ private fun createStepViewAt(i: Int): FrameLayout {
+ return FrameLayout(context).apply {
+ layoutParams =
+ FrameLayout.LayoutParams(stepProperties.width, stepProperties.height).apply {
+ setMargins(
+ /* left= */ stepProperties.horizontalMargin,
+ /* top= */ 0,
+ /* right= */ stepProperties.horizontalMargin,
+ /* bottom= */ 0
+ )
+ }
+ val drawable =
+ ShapeDrawable(
+ RoundRectShape(
+ /* outerRadii= */ radiiForIndex(i, maxLevel),
+ /* inset= */ null,
+ /* innerRadii= */ null
+ )
+ )
+ drawable.paint.color = emptyRectangleColor
+ background = drawable
+ }
+ }
+
+ private fun createBacklightIconView(): ImageView {
+ return ImageView(context).apply {
+ setImageResource(R.drawable.ic_keyboard_backlight)
+ layoutParams =
+ FrameLayout.LayoutParams(iconProperties.width, iconProperties.height).apply {
+ gravity = Gravity.CENTER
+ leftMargin = iconProperties.leftMargin
+ }
+ }
+ }
+
+ private fun setWindowTitle() {
+ val attrs = window.attributes
+ // TODO(b/271796169): check if title needs to be a translatable resource.
+ attrs.title = "KeyboardBacklightDialog"
+ attrs?.y = dialogBottomMargin
+ window.attributes = attrs
+ }
+
+ private fun setUpWindowProperties(dialog: Dialog) {
+ val window = dialog.window
+ window.requestFeature(Window.FEATURE_NO_TITLE) // otherwise fails while creating actionBar
+ window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL)
+ window.addFlags(
+ WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM or
+ WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+ )
+ window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+ window.setBackgroundDrawableResource(android.R.color.transparent)
+ window.setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL)
+ setCanceledOnTouchOutside(true)
+ }
+
+ private fun radiiForIndex(i: Int, last: Int): FloatArray {
+ val smallRadius = stepProperties.smallRadius
+ val largeRadius = stepProperties.largeRadius
+ return when (i) {
+ 0 -> // left radii bigger
+ floatArrayOf(
+ largeRadius,
+ largeRadius,
+ smallRadius,
+ smallRadius,
+ smallRadius,
+ smallRadius,
+ largeRadius,
+ largeRadius
+ )
+ last -> // right radii bigger
+ floatArrayOf(
+ smallRadius,
+ smallRadius,
+ largeRadius,
+ largeRadius,
+ largeRadius,
+ largeRadius,
+ smallRadius,
+ smallRadius
+ )
+ else -> FloatArray(8) { smallRadius } // all radii equal
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogContentViewModel.kt
new file mode 100644
index 000000000000..3ef0ca39b8f3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogContentViewModel.kt
@@ -0,0 +1,20 @@
+/*
+ * 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.keyboard.backlight.ui.viewmodel
+
+data class BacklightDialogContentViewModel(val currentValue: Int, val maxValue: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModel.kt
new file mode 100644
index 000000000000..86abca5faaf3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModel.kt
@@ -0,0 +1,72 @@
+/*
+ * 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.keyboard.backlight.ui.viewmodel
+
+import android.view.accessibility.AccessibilityManager
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyboard.backlight.domain.interactor.KeyboardBacklightInteractor
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
+import javax.inject.Inject
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.map
+
+/**
+ * Responsible for dialog visibility and content - emits [BacklightDialogContentViewModel] if dialog
+ * should be shown and hidden otherwise
+ */
+@SysUISingleton
+class BacklightDialogViewModel
+@Inject
+constructor(
+ interactor: KeyboardBacklightInteractor,
+ private val accessibilityManagerWrapper: AccessibilityManagerWrapper,
+) {
+
+ private val timeoutMillis: Long
+ get() =
+ accessibilityManagerWrapper
+ .getRecommendedTimeoutMillis(
+ DEFAULT_DIALOG_TIMEOUT_MILLIS,
+ AccessibilityManager.FLAG_CONTENT_ICONS
+ )
+ .toLong()
+
+ val dialogContent: Flow<BacklightDialogContentViewModel?> =
+ interactor.backlight
+ .filterNotNull()
+ .map { BacklightDialogContentViewModel(it.level, it.maxLevel) }
+ .timeout(timeoutMillis, emitAfterTimeout = null)
+
+ private fun <T> Flow<T>.timeout(timeoutMillis: Long, emitAfterTimeout: T): Flow<T> {
+ return flatMapLatest {
+ flow {
+ emit(it)
+ delay(timeoutMillis)
+ emit(emitAfterTimeout)
+ }
+ }
+ }
+
+ private companion object {
+ const val DEFAULT_DIALOG_TIMEOUT_MILLIS = 3000
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
new file mode 100644
index 000000000000..9449ece0933b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyboard.data.repository
+
+import android.hardware.input.InputManager
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyboard.shared.model.BacklightModel
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.shareIn
+
+interface KeyboardRepository {
+ val keyboardConnected: Flow<Boolean>
+ val backlight: Flow<BacklightModel>
+}
+
+@SysUISingleton
+class KeyboardRepositoryImpl
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val inputManager: InputManager,
+) : KeyboardRepository {
+
+ private val connectedDeviceIds: Flow<Set<Int>> =
+ conflatedCallbackFlow {
+ fun send(element: Set<Int>) = trySendWithFailureLogging(element, TAG)
+
+ var connectedKeyboards = inputManager.inputDeviceIds.toSet()
+ val listener =
+ object : InputManager.InputDeviceListener {
+ override fun onInputDeviceAdded(deviceId: Int) {
+ connectedKeyboards = connectedKeyboards + deviceId
+ send(connectedKeyboards)
+ }
+
+ override fun onInputDeviceChanged(deviceId: Int) = Unit
+
+ override fun onInputDeviceRemoved(deviceId: Int) {
+ connectedKeyboards = connectedKeyboards - deviceId
+ send(connectedKeyboards)
+ }
+ }
+ send(connectedKeyboards)
+ inputManager.registerInputDeviceListener(listener, /* handler= */ null)
+ awaitClose { inputManager.unregisterInputDeviceListener(listener) }
+ }
+ .shareIn(
+ scope = applicationScope,
+ started = SharingStarted.Lazily,
+ replay = 1,
+ )
+
+ override val keyboardConnected: Flow<Boolean> =
+ connectedDeviceIds
+ .map { it.any { deviceId -> isPhysicalFullKeyboard(deviceId) } }
+ .distinctUntilChanged()
+ .flowOn(backgroundDispatcher)
+
+ override val backlight: Flow<BacklightModel> =
+ conflatedCallbackFlow {
+ // TODO(b/268645734) register BacklightListener
+ }
+
+ private fun isPhysicalFullKeyboard(deviceId: Int): Boolean {
+ val device = inputManager.getInputDevice(deviceId)
+ return !device.isVirtual && device.isFullKeyboard
+ }
+
+ companion object {
+ const val TAG = "KeyboardRepositoryImpl"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shared/model/BacklightModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shared/model/BacklightModel.kt
new file mode 100644
index 000000000000..4a32f79285e3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shared/model/BacklightModel.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyboard.shared.model
+
+/**
+ * Model for current state of keyboard backlight brightness. [level] indicates current level of
+ * backlight brightness and [maxLevel] its max possible value.
+ */
+data class BacklightModel(val level: Int, val maxLevel: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 47872d2d68bb..4d40db0a0cfd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -638,6 +638,7 @@ public class KeyguardService extends Service {
checkPermission();
mKeyguardViewMediator.onScreenTurnedOff();
mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNED_OFF);
+ mScreenOnCoordinator.onScreenTurnedOff();
}
@Override // Binder interface
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index f964cb39a8d4..90562dc4a243 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -380,10 +380,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
// If the launcher is underneath, but we're about to launch an activity, don't do
// the animations since they won't be visible.
!notificationShadeWindowController.isLaunchingActivity &&
- launcherUnlockController != null &&
- // Temporarily disable for foldables since foldable launcher has two first pages,
- // which breaks the in-window animation.
- !isFoldable(context)
+ launcherUnlockController != null
}
/**
@@ -950,9 +947,9 @@ class KeyguardUnlockAnimationController @Inject constructor(
return false
}
- // We don't do the shared element on tablets because they're large and the smartspace has to
- // fly across large distances, which is distracting.
- if (Utilities.isTablet(context)) {
+ // We don't do the shared element on large screens because the smartspace has to fly across
+ // large distances, which is distracting.
+ if (Utilities.isLargeScreen(context)) {
return false
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6db1f8959e8a..2815df68ad0a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -58,6 +58,7 @@ import android.hardware.biometrics.BiometricSourceType;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
+import android.os.Binder;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
@@ -66,6 +67,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
@@ -101,6 +103,7 @@ import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardStateCallback;
import com.android.internal.policy.ScreenDecorationsUtils;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardConstants;
@@ -123,8 +126,6 @@ import com.android.systemui.classifier.FalsingCollector;
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.navigationbar.NavigationModeController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -269,6 +270,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
private AlarmManager mAlarmManager;
private AudioManager mAudioManager;
private StatusBarManager mStatusBarManager;
+ private final IStatusBarService mStatusBarService;
+ private final IBinder mStatusBarDisableToken = new Binder();
private final UserTracker mUserTracker;
private final SysuiStatusBarStateController mStatusBarStateController;
private final Executor mUiBgExecutor;
@@ -510,8 +513,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
private CentralSurfaces mCentralSurfaces;
- private boolean mUnocclusionTransitionFlagEnabled = false;
-
private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
new DeviceConfig.OnPropertiesChangedListener() {
@Override
@@ -963,16 +964,24 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
- if (!mUnocclusionTransitionFlagEnabled) {
- setOccluded(true /* isOccluded */, true /* animate */);
+ if (!handleOnAnimationStart(
+ transit, apps, wallpapers, nonApps, finishedCallback)) {
+ // Usually we rely on animation completion to synchronize occluded status,
+ // but there was no animation to play, so just update it now.
+ setOccluded(true /* isOccluded */, false /* animate */);
}
+ }
+
+ private boolean handleOnAnimationStart(int transit, RemoteAnimationTarget[] apps,
+ RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
+ IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
if (apps == null || apps.length == 0 || apps[0] == null) {
if (DEBUG) {
Log.d(TAG, "No apps provided to the OccludeByDream runner; "
+ "skipping occluding animation.");
}
finishedCallback.onAnimationFinished();
- return;
+ return false;
}
final RemoteAnimationTarget primary = apps[0];
@@ -982,7 +991,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
Log.w(TAG, "The occluding app isn't Dream; "
+ "finishing up. Please check that the config is correct.");
finishedCallback.onAnimationFinished();
- return;
+ return false;
}
final SyncRtSurfaceTransactionApplier applier =
@@ -1016,7 +1025,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
@Override
public void onAnimationEnd(Animator animation) {
try {
- if (!mIsCancelled && mUnocclusionTransitionFlagEnabled) {
+ if (!mIsCancelled) {
// We're already on the main thread, don't queue this call
handleSetOccluded(true /* isOccluded */,
false /* animate */);
@@ -1031,6 +1040,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
mOccludeByDreamAnimator.start();
});
+ return true;
}
};
@@ -1193,7 +1203,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
ScreenOnCoordinator screenOnCoordinator,
InteractionJankMonitor interactionJankMonitor,
DreamOverlayStateController dreamOverlayStateController,
- FeatureFlags featureFlags,
Lazy<ShadeController> shadeControllerLazy,
Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy,
Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
@@ -1211,6 +1220,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
mPM = powerManager;
mTrustManager = trustManager;
mUserSwitcherController = userSwitcherController;
+ mStatusBarService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mKeyguardDisplayManager = keyguardDisplayManager;
mShadeController = shadeControllerLazy;
dumpManager.registerDumpable(getClass().getName(), this);
@@ -1250,7 +1261,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
mDreamOpenAnimationDuration = (int) DREAMING_ANIMATION_DURATION_MS;
mDreamCloseAnimationDuration = (int) LOCKSCREEN_ANIMATION_DURATION_MS;
- mUnocclusionTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
}
public void userActivity() {
@@ -1922,20 +1932,24 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
// If the keyguard is already showing, see if we don't need to bother re-showing it. Check
// flags in both files to account for the hiding animation which results in a delay and
- // discrepancy between flags.
+ // discrepancy between flags. If we're in the middle of hiding, do not short circuit so that
+ // we explicitly re-set state.
if (mShowing && mKeyguardStateController.isShowing()) {
- if (mPM.isInteractive()) {
+ if (mPM.isInteractive() && !mHiding) {
// It's already showing, and we're not trying to show it while the screen is off.
// We can simply reset all of the views.
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
+ if (DEBUG) Log.d(TAG, "doKeyguard: not showing (instead, resetting) because it is "
+ + "already showing, we're interactive, and we were not previously hiding. "
+ + "It should be safe to short-circuit here.");
resetStateLocked();
return;
} else {
- // We are trying to show the keyguard while the screen is off - this results from
- // race conditions involving locking while unlocking. Don't short-circuit here and
- // ensure the keyguard is fully re-shown.
+ // We are trying to show the keyguard while the screen is off or while we were in
+ // the middle of hiding - this results from race conditions involving locking while
+ // unlocking. Don't short-circuit here and ensure the keyguard is fully re-shown.
Log.e(TAG,
- "doKeyguard: already showing, but re-showing since we're not interactive");
+ "doKeyguard: already showing, but re-showing because we're interactive or "
+ + "were in the middle of hiding.");
}
}
@@ -2429,11 +2443,19 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
if (DEBUG) Log.d(TAG, "handleShow");
}
- mHiding = false;
mKeyguardExitAnimationRunner = null;
mWakeAndUnlocking = false;
setPendingLock(false);
- setShowingLocked(true);
+
+ // Force if we we're showing in the middle of hiding, to ensure we end up in the correct
+ // state.
+ setShowingLocked(true, mHiding /* force */);
+ if (mHiding) {
+ Log.d(TAG, "Forcing setShowingLocked because mHiding=true, which means we're "
+ + "showing in the middle of hiding.");
+ }
+ mHiding = false;
+
mKeyguardViewControllerLazy.get().show(options);
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
@@ -2931,7 +2953,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
// TODO (b/155663717) After restart, status bar will not properly hide home button
// unless disable is called to show un-hide it once first
if (forceClearFlags) {
- mStatusBarManager.disable(flags);
+ try {
+ mStatusBarService.disableForUser(flags, mStatusBarDisableToken,
+ mContext.getPackageName(), mUserTracker.getUserId());
+ } catch (RemoteException e) {
+ Log.d(TAG, "Failed to force clear flags", e);
+ }
}
if (forceHideHomeRecentsButtons || isShowingAndNotOccluded()) {
@@ -2947,7 +2974,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
+ " --> flags=0x" + Integer.toHexString(flags));
}
- mStatusBarManager.disable(flags);
+ try {
+ mStatusBarService.disableForUser(flags, mStatusBarDisableToken,
+ mContext.getPackageName(), mUserTracker.getUserId());
+ } catch (RemoteException e) {
+ Log.d(TAG, "Failed to set disable flags: " + flags, e);
+ }
}
}
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 98d3570106ce..47ef0fac17ab 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -39,7 +39,6 @@ import com.android.systemui.dagger.SysUISingleton;
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.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -113,7 +112,6 @@ public class KeyguardModule {
ScreenOnCoordinator screenOnCoordinator,
InteractionJankMonitor interactionJankMonitor,
DreamOverlayStateController dreamOverlayStateController,
- FeatureFlags featureFlags,
Lazy<ShadeController> shadeController,
Lazy<NotificationShadeWindowController> notificationShadeWindowController,
Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
@@ -144,7 +142,6 @@ public class KeyguardModule {
screenOnCoordinator,
interactionJankMonitor,
dreamOverlayStateController,
- featureFlags,
shadeController,
notificationShadeWindowController,
activityLaunchAnimator,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt
index faeb48526ae4..871a3ff63214 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt
@@ -52,6 +52,8 @@ interface BouncerViewDelegate {
cancelAction: Runnable?,
)
fun willDismissWithActions(): Boolean
+ fun willRunDismissFromKeyguard(): Boolean
/** @return the {@link OnBackAnimationCallback} to animate Bouncer during a back gesture. */
fun getBackCallback(): OnBackAnimationCallback
+ fun showPromptReason(reason: Int)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
index be73f851fa82..ef0c9a175141 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
@@ -134,7 +134,9 @@ constructor(
.flowOn(backgroundDispatcher)
.distinctUntilChanged()
.onEach { settingsValue = it }
- ) { callbackFlowValue, _ -> callbackFlowValue }
+ ) { callbackFlowValue, _ ->
+ callbackFlowValue
+ }
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
return if (controller.isZenAvailable) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
index 006678546de8..356a8fb65883 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
@@ -102,7 +102,8 @@ constructor(
// setup).
emit(Unit)
}
- ) { _, _ -> }
+ ) { _, _ ->
+ }
.flatMapLatest {
conflatedCallbackFlow {
// We want to instantiate a new SharedPreferences instance each time either the
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
index baadc66170cc..84abf57cacf2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
@@ -24,8 +24,10 @@ import android.hardware.biometrics.BiometricManager
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback
import android.os.Looper
import android.os.UserHandle
+import android.util.Log
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.Dumpable
+import com.android.systemui.R
import com.android.systemui.biometrics.AuthController
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
@@ -35,6 +37,7 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.shared.model.DevicePosture
import com.android.systemui.user.data.repository.UserRepository
import java.io.PrintWriter
import javax.inject.Inject
@@ -47,8 +50,10 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
@@ -82,6 +87,12 @@ interface BiometricSettingsRepository {
/** Whether fingerprint feature is enabled for the current user by the DevicePolicy */
val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean>
+
+ /**
+ * Whether face authentication is supported for the current device posture. Face auth can be
+ * restricted to specific postures using [R.integer.config_face_auth_supported_posture]
+ */
+ val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
}
@SysUISingleton
@@ -98,11 +109,27 @@ constructor(
@Background backgroundDispatcher: CoroutineDispatcher,
biometricManager: BiometricManager?,
@Main looper: Looper,
+ devicePostureRepository: DevicePostureRepository,
dumpManager: DumpManager,
) : BiometricSettingsRepository, Dumpable {
+ override val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
+
init {
dumpManager.registerDumpable(this)
+ val configFaceAuthSupportedPosture =
+ DevicePosture.toPosture(
+ context.resources.getInteger(R.integer.config_face_auth_supported_posture)
+ )
+ isFaceAuthSupportedInCurrentPosture =
+ if (configFaceAuthSupportedPosture == DevicePosture.UNKNOWN) {
+ flowOf(true)
+ } else {
+ devicePostureRepository.currentDevicePosture.map {
+ it == configFaceAuthSupportedPosture
+ }
+ }
+ .onEach { Log.d(TAG, "isFaceAuthSupportedInCurrentPosture value changed to: $it") }
}
override fun dump(pw: PrintWriter, args: Array<String?>) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt
new file mode 100644
index 000000000000..adb1e01d0d00
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt
@@ -0,0 +1,58 @@
+/*
+ * 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.keyguard.data.repository
+
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+
+/** Provide current device posture state. */
+interface DevicePostureRepository {
+ /** Provides the current device posture. */
+ val currentDevicePosture: Flow<DevicePosture>
+}
+
+@SysUISingleton
+class DevicePostureRepositoryImpl
+@Inject
+constructor(private val postureController: DevicePostureController) : DevicePostureRepository {
+ override val currentDevicePosture: Flow<DevicePosture>
+ get() = conflatedCallbackFlow {
+ val sendPostureUpdate = { posture: Int ->
+ val currentDevicePosture = DevicePosture.toPosture(posture)
+ trySendWithFailureLogging(
+ currentDevicePosture,
+ TAG,
+ "Error sending posture update to $currentDevicePosture"
+ )
+ }
+ val callback = DevicePostureController.Callback { sendPostureUpdate(it) }
+ postureController.addCallback(callback)
+ sendPostureUpdate(postureController.devicePosture)
+
+ awaitClose { postureController.removeCallback(callback) }
+ }
+
+ companion object {
+ const val TAG = "PostureRepositoryImpl"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
index 4331fe66a0dc..ae5b79947006 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
@@ -22,7 +22,6 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import com.android.systemui.log.dagger.BouncerLog
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
@@ -43,16 +42,15 @@ import kotlinx.coroutines.flow.map
*/
interface KeyguardBouncerRepository {
/** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
- val primaryBouncerVisible: StateFlow<Boolean>
- val primaryBouncerShow: StateFlow<KeyguardBouncerModel?>
+ val primaryBouncerShow: StateFlow<Boolean>
val primaryBouncerShowingSoon: StateFlow<Boolean>
- val primaryBouncerHide: StateFlow<Boolean>
val primaryBouncerStartingToHide: StateFlow<Boolean>
val primaryBouncerStartingDisappearAnimation: StateFlow<Runnable?>
/** Determines if we want to instantaneously show the primary bouncer instead of translating. */
val primaryBouncerScrimmed: StateFlow<Boolean>
/**
* Set how much of the notification panel is showing on the screen.
+ *
* ```
* 0f = panel fully hidden = bouncer fully showing
* 1f = panel fully showing = bouncer fully hidden
@@ -60,7 +58,6 @@ interface KeyguardBouncerRepository {
*/
val panelExpansionAmount: StateFlow<Float>
val keyguardPosition: StateFlow<Float>
- val onScreenTurnedOff: StateFlow<Boolean>
val isBackButtonEnabled: StateFlow<Boolean?>
/** Determines if user is already unlocked */
val keyguardAuthenticated: StateFlow<Boolean?>
@@ -70,18 +67,16 @@ interface KeyguardBouncerRepository {
val bouncerErrorMessage: CharSequence?
val alternateBouncerVisible: StateFlow<Boolean>
val alternateBouncerUIAvailable: StateFlow<Boolean>
+ val sideFpsShowing: StateFlow<Boolean>
+
var lastAlternateBouncerVisibleTime: Long
fun setPrimaryScrimmed(isScrimmed: Boolean)
- fun setPrimaryVisible(isVisible: Boolean)
-
- fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?)
+ fun setPrimaryShow(isShowing: Boolean)
fun setPrimaryShowingSoon(showingSoon: Boolean)
- fun setPrimaryHide(hide: Boolean)
-
fun setPrimaryStartingToHide(startingToHide: Boolean)
fun setPrimaryStartDisappearAnimation(runnable: Runnable?)
@@ -98,11 +93,11 @@ interface KeyguardBouncerRepository {
fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean)
- fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean)
-
fun setAlternateVisible(isVisible: Boolean)
fun setAlternateBouncerUIAvailable(isAvailable: Boolean)
+
+ fun setSideFpsShowing(isShowing: Boolean)
}
@SysUISingleton
@@ -115,14 +110,10 @@ constructor(
@BouncerLog private val buffer: TableLogBuffer,
) : KeyguardBouncerRepository {
/** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
- private val _primaryBouncerVisible = MutableStateFlow(false)
- override val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow()
- private val _primaryBouncerShow = MutableStateFlow<KeyguardBouncerModel?>(null)
+ private val _primaryBouncerShow = MutableStateFlow(false)
override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
private val _primaryBouncerShowingSoon = MutableStateFlow(false)
override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
- private val _primaryBouncerHide = MutableStateFlow(false)
- override val primaryBouncerHide = _primaryBouncerHide.asStateFlow()
private val _primaryBouncerStartingToHide = MutableStateFlow(false)
override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
@@ -133,6 +124,7 @@ constructor(
override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
/**
* Set how much of the notification panel is showing on the screen.
+ *
* ```
* 0f = panel fully hidden = bouncer fully showing
* 1f = panel fully showing = bouncer fully hidden
@@ -142,8 +134,6 @@ constructor(
override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
private val _keyguardPosition = MutableStateFlow(0f)
override val keyguardPosition = _keyguardPosition.asStateFlow()
- private val _onScreenTurnedOff = MutableStateFlow(false)
- override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
@@ -165,6 +155,8 @@ constructor(
private val _alternateBouncerUIAvailable = MutableStateFlow(false)
override val alternateBouncerUIAvailable: StateFlow<Boolean> =
_alternateBouncerUIAvailable.asStateFlow()
+ private val _sideFpsShowing = MutableStateFlow(false)
+ override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow()
init {
setUpLogging()
@@ -174,10 +166,6 @@ constructor(
_primaryBouncerScrimmed.value = isScrimmed
}
- override fun setPrimaryVisible(isVisible: Boolean) {
- _primaryBouncerVisible.value = isVisible
- }
-
override fun setAlternateVisible(isVisible: Boolean) {
if (isVisible && !_alternateBouncerVisible.value) {
lastAlternateBouncerVisibleTime = clock.uptimeMillis()
@@ -191,18 +179,14 @@ constructor(
_alternateBouncerUIAvailable.value = isAvailable
}
- override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
- _primaryBouncerShow.value = keyguardBouncerModel
+ override fun setPrimaryShow(isShowing: Boolean) {
+ _primaryBouncerShow.value = isShowing
}
override fun setPrimaryShowingSoon(showingSoon: Boolean) {
_primaryBouncerShowingSoon.value = showingSoon
}
- override fun setPrimaryHide(hide: Boolean) {
- _primaryBouncerHide.value = hide
- }
-
override fun setPrimaryStartingToHide(startingToHide: Boolean) {
_primaryBouncerStartingToHide.value = startingToHide
}
@@ -235,8 +219,8 @@ constructor(
_isBackButtonEnabled.value = isBackButtonEnabled
}
- override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
- _onScreenTurnedOff.value = onScreenTurnedOff
+ override fun setSideFpsShowing(isShowing: Boolean) {
+ _sideFpsShowing.value = isShowing
}
/** Sets up logs for state flows. */
@@ -245,19 +229,12 @@ constructor(
return
}
- primaryBouncerVisible
- .logDiffsForTable(buffer, "", "PrimaryBouncerVisible", false)
- .launchIn(applicationScope)
primaryBouncerShow
- .map { it != null }
.logDiffsForTable(buffer, "", "PrimaryBouncerShow", false)
.launchIn(applicationScope)
primaryBouncerShowingSoon
.logDiffsForTable(buffer, "", "PrimaryBouncerShowingSoon", false)
.launchIn(applicationScope)
- primaryBouncerHide
- .logDiffsForTable(buffer, "", "PrimaryBouncerHide", false)
- .launchIn(applicationScope)
primaryBouncerStartingToHide
.logDiffsForTable(buffer, "", "PrimaryBouncerStartingToHide", false)
.launchIn(applicationScope)
@@ -276,9 +253,6 @@ constructor(
.map { it.toInt() }
.logDiffsForTable(buffer, "", "KeyguardPosition", -1)
.launchIn(applicationScope)
- onScreenTurnedOff
- .logDiffsForTable(buffer, "", "OnScreenTurnedOff", false)
- .launchIn(applicationScope)
isBackButtonEnabled
.filterNotNull()
.logDiffsForTable(buffer, "", "IsBackButtonEnabled", false)
@@ -293,6 +267,9 @@ constructor(
alternateBouncerUIAvailable
.logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false)
.launchIn(applicationScope)
+ sideFpsShowing
+ .logDiffsForTable(buffer, "", "isSideFpsShowing", false)
+ .launchIn(applicationScope)
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index a3b3d0fd0681..76f20d25b0ec 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -80,6 +80,9 @@ interface KeyguardRepository {
*/
val isKeyguardShowing: Flow<Boolean>
+ /** Is the keyguard in a unlocked state? */
+ val isKeyguardUnlocked: Flow<Boolean>
+
/** Is an activity showing over the keyguard? */
val isKeyguardOccluded: Flow<Boolean>
@@ -278,6 +281,31 @@ constructor(
}
.distinctUntilChanged()
+ override val isKeyguardUnlocked: Flow<Boolean> =
+ conflatedCallbackFlow {
+ val callback =
+ object : KeyguardStateController.Callback {
+ override fun onUnlockedChanged() {
+ trySendWithFailureLogging(
+ keyguardStateController.isUnlocked,
+ TAG,
+ "updated isKeyguardUnlocked"
+ )
+ }
+ }
+
+ keyguardStateController.addCallback(callback)
+ // Adding the callback does not send an initial update.
+ trySendWithFailureLogging(
+ keyguardStateController.isUnlocked,
+ TAG,
+ "initial isKeyguardUnlocked"
+ )
+
+ awaitClose { keyguardStateController.removeCallback(callback) }
+ }
+ .distinctUntilChanged()
+
override val isKeyguardGoingAway: Flow<Boolean> = conflatedCallbackFlow {
val callback =
object : KeyguardStateController.Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
index 4a262f580749..f27f89995dbd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
@@ -31,6 +31,8 @@ interface KeyguardRepositoryModule {
@Binds
fun lightRevealScrimRepository(impl: LightRevealScrimRepositoryImpl): LightRevealScrimRepository
+ @Binds fun devicePostureRepository(impl: DevicePostureRepositoryImpl): DevicePostureRepository
+
@Binds
fun biometricSettingsRepository(
impl: BiometricSettingsRepositoryImpl
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 0c4bca616e12..100bc596103d 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
@@ -68,8 +68,11 @@ interface KeyguardTransitionRepository {
/**
* Begin a transition from one state to another. Transitions are interruptible, and will issue a
* [TransitionStep] with state = [TransitionState.CANCELED] before beginning the next one.
+ *
+ * When canceled, there are two options: to continue from the current position of the prior
+ * transition, or to reset the position. When [resetIfCanceled] == true, it will do the latter.
*/
- fun startTransition(info: TransitionInfo): UUID?
+ fun startTransition(info: TransitionInfo, resetIfCanceled: Boolean = false): UUID?
/**
* Allows manual control of a transition. When calling [startTransition], the consumer must pass
@@ -130,7 +133,10 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
)
}
- override fun startTransition(info: TransitionInfo): UUID? {
+ override fun startTransition(
+ info: TransitionInfo,
+ resetIfCanceled: Boolean,
+ ): UUID? {
if (lastStep.from == info.from && lastStep.to == info.to) {
Log.i(TAG, "Duplicate call to start the transition, rejecting: $info")
return null
@@ -138,7 +144,11 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
val startingValue =
if (lastStep.transitionState != TransitionState.FINISHED) {
Log.i(TAG, "Transition still active: $lastStep, canceling")
- lastStep.value
+ if (resetIfCanceled) {
+ 0f
+ } else {
+ lastStep.value
+ }
} else {
0f
}
@@ -227,10 +237,7 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
}
private fun trace(step: TransitionStep, isManual: Boolean) {
- if (
- step.transitionState != TransitionState.STARTED &&
- step.transitionState != TransitionState.FINISHED
- ) {
+ if (step.transitionState == TransitionState.RUNNING) {
return
}
val traceName =
@@ -243,7 +250,10 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
val traceCookie = traceName.hashCode()
if (step.transitionState == TransitionState.STARTED) {
Trace.beginAsyncSection(traceName, traceCookie)
- } else if (step.transitionState == TransitionState.FINISHED) {
+ } else if (
+ step.transitionState == TransitionState.FINISHED ||
+ step.transitionState == TransitionState.CANCELED
+ ) {
Trace.endAsyncSection(traceName, traceCookie)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
index dfe10381720c..eae40d61cdb6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
@@ -24,6 +24,7 @@ import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.LegacyAlternateBouncer
+import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -33,6 +34,7 @@ import kotlinx.coroutines.flow.Flow
class AlternateBouncerInteractor
@Inject
constructor(
+ private val keyguardStateController: KeyguardStateController,
private val bouncerRepository: KeyguardBouncerRepository,
private val biometricSettingsRepository: BiometricSettingsRepository,
private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
@@ -48,6 +50,7 @@ constructor(
/**
* Sets the correct bouncer states to show the alternate bouncer if it can show.
+ *
* @return whether alternateBouncer is visible
*/
fun show(): Boolean {
@@ -72,6 +75,7 @@ constructor(
* Sets the correct bouncer states to hide the bouncer. Should only be called through
* StatusBarKeyguardViewManager until ScrimController is refactored to use
* alternateBouncerInteractor.
+ *
* @return true if the alternate bouncer was newly hidden, else false.
*/
fun hide(): Boolean {
@@ -102,7 +106,8 @@ constructor(
biometricSettingsRepository.isFingerprintEnrolled.value &&
biometricSettingsRepository.isStrongBiometricAllowed.value &&
biometricSettingsRepository.isFingerprintEnabledByDevicePolicy.value &&
- !deviceEntryFingerprintAuthRepository.isLockedOut.value
+ !deviceEntryFingerprintAuthRepository.isLockedOut.value &&
+ !keyguardStateController.isUnlocked
} else {
legacyAlternateBouncer != null &&
keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(true)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
index 310f44da6e66..e6568f20bc20 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
@@ -71,8 +71,7 @@ constructor(
isPrimaryBouncerShowing,
lastStartedTransitionStep,
wakefulnessState,
- isAodAvailable
- ) ->
+ isAodAvailable) ->
if (
!isAlternateBouncerShowing &&
!isPrimaryBouncerShowing &&
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 8715d1f55069..3beac0b1322e 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
@@ -34,7 +34,6 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@@ -57,14 +56,7 @@ constructor(
private fun listenForDreamingToLockscreen() {
scope.launch {
- // Dependending on the dream, either dream state or occluded change will change first,
- // so listen for both
- combine(keyguardInteractor.isAbleToDream, keyguardInteractor.isKeyguardOccluded) {
- isAbleToDream,
- isKeyguardOccluded ->
- isAbleToDream && isKeyguardOccluded
- }
- .distinctUntilChanged()
+ keyguardInteractor.isAbleToDream
.sample(
combine(
keyguardInteractor.dozeTransitionModel,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index d01f48970c97..28cc69758308 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -64,7 +64,11 @@ constructor(
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
.collect { pair ->
val (isAbleToDream, lastStartedTransition) = pair
- if (isAbleToDream && lastStartedTransition.to == KeyguardState.LOCKSCREEN) {
+ if (
+ isAbleToDream &&
+ lastStartedTransition.to == KeyguardState.LOCKSCREEN &&
+ lastStartedTransition.from != KeyguardState.AOD
+ ) {
keyguardTransitionRepository.startTransition(
TransitionInfo(
name,
@@ -130,55 +134,59 @@ constructor(
shadeRepository.shadeModel
.sample(
combine(
- keyguardTransitionInteractor.finishedKeyguardState,
+ keyguardTransitionInteractor.startedKeyguardTransitionStep,
keyguardInteractor.statusBarState,
- ::Pair
+ keyguardInteractor.isKeyguardUnlocked,
+ ::toTriple
),
- ::toTriple
+ ::toQuad
)
- .collect { (shadeModel, keyguardState, statusBarState) ->
+ .collect { (shadeModel, keyguardState, statusBarState, isKeyguardUnlocked) ->
val id = transitionId
if (id != null) {
- // An existing `id` means a transition is started, and calls to
- // `updateTransition` will control it until FINISHED or CANCELED
- var nextState =
- if (shadeModel.expansionAmount == 0f) {
- TransitionState.FINISHED
- } else if (shadeModel.expansionAmount == 1f) {
- TransitionState.CANCELED
- } else {
- TransitionState.RUNNING
- }
- keyguardTransitionRepository.updateTransition(
- id,
- 1f - shadeModel.expansionAmount,
- nextState,
- )
+ if (keyguardState.to == KeyguardState.PRIMARY_BOUNCER) {
+ // An existing `id` means a transition is started, and calls to
+ // `updateTransition` will control it until FINISHED or CANCELED
+ var nextState =
+ if (shadeModel.expansionAmount == 0f) {
+ TransitionState.FINISHED
+ } else if (shadeModel.expansionAmount == 1f) {
+ TransitionState.CANCELED
+ } else {
+ TransitionState.RUNNING
+ }
+ keyguardTransitionRepository.updateTransition(
+ id,
+ 1f - shadeModel.expansionAmount,
+ nextState,
+ )
- if (
- nextState == TransitionState.CANCELED ||
- nextState == TransitionState.FINISHED
- ) {
- transitionId = null
- }
+ if (
+ nextState == TransitionState.CANCELED ||
+ nextState == TransitionState.FINISHED
+ ) {
+ transitionId = null
+ }
- // If canceled, just put the state back
- if (nextState == TransitionState.CANCELED) {
- keyguardTransitionRepository.startTransition(
- TransitionInfo(
- ownerName = name,
- from = KeyguardState.PRIMARY_BOUNCER,
- to = KeyguardState.LOCKSCREEN,
- animator = getAnimator(0.milliseconds)
+ // If canceled, just put the state back
+ if (nextState == TransitionState.CANCELED) {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ ownerName = name,
+ from = KeyguardState.PRIMARY_BOUNCER,
+ to = KeyguardState.LOCKSCREEN,
+ animator = getAnimator(0.milliseconds)
+ )
)
- )
+ }
}
} else {
// TODO (b/251849525): Remove statusbarstate check when that state is
// integrated into KeyguardTransitionRepository
if (
- keyguardState == KeyguardState.LOCKSCREEN &&
+ keyguardState.to == KeyguardState.LOCKSCREEN &&
shadeModel.isUserDragging &&
+ !isKeyguardUnlocked &&
statusBarState == KEYGUARD
) {
transitionId =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
index 2dc8fee25379..1fbfff95ab7e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
@@ -47,6 +47,7 @@ constructor(
listenForOccludedToLockscreen()
listenForOccludedToDreaming()
listenForOccludedToAodOrDozing()
+ listenForOccludedToGone()
}
private fun listenForOccludedToDreaming() {
@@ -72,11 +73,22 @@ constructor(
private fun listenForOccludedToLockscreen() {
scope.launch {
keyguardInteractor.isKeyguardOccluded
- .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
- .collect { (isOccluded, lastStartedKeyguardState) ->
+ .sample(
+ combine(
+ keyguardInteractor.isKeyguardShowing,
+ keyguardTransitionInteractor.startedKeyguardTransitionStep,
+ ::Pair
+ ),
+ ::toTriple
+ )
+ .collect { (isOccluded, isShowing, lastStartedKeyguardState) ->
// Occlusion signals come from the framework, and should interrupt any
// existing transition
- if (!isOccluded && lastStartedKeyguardState.to == KeyguardState.OCCLUDED) {
+ if (
+ !isOccluded &&
+ isShowing &&
+ lastStartedKeyguardState.to == KeyguardState.OCCLUDED
+ ) {
keyguardTransitionRepository.startTransition(
TransitionInfo(
name,
@@ -90,6 +102,38 @@ constructor(
}
}
+ private fun listenForOccludedToGone() {
+ scope.launch {
+ keyguardInteractor.isKeyguardOccluded
+ .sample(
+ combine(
+ keyguardInteractor.isKeyguardShowing,
+ keyguardTransitionInteractor.startedKeyguardTransitionStep,
+ ::Pair
+ ),
+ ::toTriple
+ )
+ .collect { (isOccluded, isShowing, lastStartedKeyguardState) ->
+ // Occlusion signals come from the framework, and should interrupt any
+ // existing transition
+ if (
+ !isOccluded &&
+ !isShowing &&
+ lastStartedKeyguardState.to == KeyguardState.OCCLUDED
+ ) {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ name,
+ KeyguardState.OCCLUDED,
+ KeyguardState.GONE,
+ getAnimator(),
+ )
+ )
+ }
+ }
+ }
+ }
+
private fun listenForOccludedToAodOrDozing() {
scope.launch {
keyguardInteractor.wakefulnessModel
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
index b59b413d7a40..94961cbf4240 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
@@ -17,6 +17,9 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Password
+import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
@@ -26,6 +29,8 @@ import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
@@ -37,7 +42,8 @@ constructor(
@Application private val scope: CoroutineScope,
private val keyguardInteractor: KeyguardInteractor,
private val keyguardTransitionRepository: KeyguardTransitionRepository,
- private val keyguardTransitionInteractor: KeyguardTransitionInteractor
+ private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+ private val keyguardSecurityModel: KeyguardSecurityModel,
) : TransitionInteractor(FromPrimaryBouncerTransitionInteractor::class.simpleName!!) {
override fun start() {
@@ -93,31 +99,47 @@ constructor(
private fun listenForPrimaryBouncerToGone() {
scope.launch {
keyguardInteractor.isKeyguardGoingAway
- .sample(keyguardTransitionInteractor.finishedKeyguardState) { a, b -> Pair(a, b) }
- .collect { pair ->
- val (isKeyguardGoingAway, keyguardState) = pair
- if (isKeyguardGoingAway && keyguardState == KeyguardState.PRIMARY_BOUNCER) {
+ .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
+ .collect { (isKeyguardGoingAway, lastStartedTransitionStep) ->
+ if (
+ isKeyguardGoingAway &&
+ lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER
+ ) {
+ val securityMode =
+ keyguardSecurityModel.getSecurityMode(
+ KeyguardUpdateMonitor.getCurrentUser()
+ )
+ // IME for password requires a slightly faster animation
+ val duration =
+ if (securityMode == Password) {
+ TO_GONE_SHORT_DURATION
+ } else {
+ TO_GONE_DURATION
+ }
keyguardTransitionRepository.startTransition(
TransitionInfo(
ownerName = name,
from = KeyguardState.PRIMARY_BOUNCER,
to = KeyguardState.GONE,
- animator = getAnimator(),
- )
+ animator = getAnimator(duration),
+ ),
+ resetIfCanceled = true,
)
}
}
}
}
- private fun getAnimator(): ValueAnimator {
+ private fun getAnimator(duration: Duration = DEFAULT_DURATION): ValueAnimator {
return ValueAnimator().apply {
setInterpolator(Interpolators.LINEAR)
- setDuration(TRANSITION_DURATION_MS)
+ setDuration(duration.inWholeMilliseconds)
}
}
companion object {
- private const val TRANSITION_DURATION_MS = 300L
+ private val DEFAULT_DURATION = 300.milliseconds
+ val TO_GONE_DURATION = 250.milliseconds
+ val TO_GONE_SHORT_DURATION = 200.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 d25aff0add86..1ac0c526f975 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
@@ -33,7 +33,9 @@ import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDoz
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isWakingOrStartingToWake
import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
@@ -95,6 +97,9 @@ constructor(
awaitClose { commandQueue.removeCallback(callback) }
}
+ /** The device wake/sleep state */
+ val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness
+
/**
* Dozing and dreaming have overlapping events. If the doze state remains in FINISH, it means
* that doze mode is not running and DREAMING is ok to commence.
@@ -109,6 +114,12 @@ constructor(
isDreaming && isDozeOff(dozeTransitionModel.to)
}
)
+ .sample(
+ wakefulnessModel,
+ { isAbleToDream, wakefulnessModel ->
+ isAbleToDream && isWakingOrStartingToWake(wakefulnessModel)
+ }
+ )
.flatMapLatest { isAbleToDream ->
flow {
delay(50)
@@ -119,18 +130,20 @@ constructor(
/** Whether the keyguard is showing or not. */
val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
+ /** Whether the keyguard is unlocked or not. */
+ val isKeyguardUnlocked: Flow<Boolean> = repository.isKeyguardUnlocked
/** Whether the keyguard is occluded (covered by an activity). */
val isKeyguardOccluded: Flow<Boolean> = repository.isKeyguardOccluded
/** Whether the keyguard is going away. */
val isKeyguardGoingAway: Flow<Boolean> = repository.isKeyguardGoingAway
/** Whether the primary bouncer is showing or not. */
- val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerVisible
+ val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow
/** Whether the alternate bouncer is showing or not. */
val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
- /** The device wake/sleep state */
- val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness
/** Observable for the [StatusBarState] */
val statusBarState: Flow<StatusBarState> = repository.statusBarState
+ /** Whether or not quick settings or quick quick settings are showing. */
+ val isQuickSettingsVisible: Flow<Boolean> = repository.isQuickSettingsVisible
/**
* Observable for [BiometricUnlockModel] when biometrics like face or any fingerprint (rear,
* side, under display) is used to unlock the device.
@@ -146,7 +159,7 @@ constructor(
if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) {
combine(
isKeyguardVisible,
- bouncerRepository.primaryBouncerVisible,
+ primaryBouncerShowing,
onCameraLaunchDetected,
) { isKeyguardVisible, isPrimaryBouncerShowing, cameraLaunchEvent ->
when {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index dfbe1c216847..66f87bade308 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -93,8 +93,9 @@ constructor(
quickAffordanceAlwaysVisible(position),
keyguardInteractor.isDozing,
keyguardInteractor.isKeyguardShowing,
- ) { affordance, isDozing, isKeyguardShowing ->
- if (!isDozing && isKeyguardShowing) {
+ keyguardInteractor.isQuickSettingsVisible
+ ) { affordance, isDozing, isKeyguardShowing, isQuickSettingsVisible ->
+ if (!isDozing && isKeyguardShowing && !isQuickSettingsVisible) {
affordance
} else {
KeyguardQuickAffordanceModel.Hidden
@@ -119,7 +120,7 @@ constructor(
* Notifies that a quick affordance has been "triggered" (clicked) by the user.
*
* @param configKey The configuration key corresponding to the [KeyguardQuickAffordanceModel] of
- * the affordance that was clicked
+ * the affordance that was clicked
* @param expandable An optional [Expandable] for the activity- or dialog-launch animation
*/
fun onQuickAffordanceTriggered(
@@ -198,9 +199,9 @@ constructor(
*
* @param slotId The ID of the slot.
* @param affordanceId The ID of the affordance to remove; if `null`, removes all affordances
- * from the slot.
+ * from the slot.
* @return `true` if the affordance was successfully removed; `false` otherwise (for example, if
- * the affordance was not on the slot to begin with).
+ * the affordance was not on the slot to begin with).
*/
suspend fun unselect(slotId: String, affordanceId: String?): Boolean {
check(isUsingRepository)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
index 51b02779a89f..e650b9fc0e47 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
@@ -61,7 +61,15 @@ constructor(
}
scope.launch {
- keyguardInteractor.isDreaming.collect { logger.log(TAG, VERBOSE, "isDreaming", it) }
+ keyguardInteractor.isAbleToDream.collect {
+ logger.log(TAG, VERBOSE, "isAbleToDream", it)
+ }
+ }
+
+ scope.launch {
+ keyguardInteractor.isKeyguardOccluded.collect {
+ logger.log(TAG, VERBOSE, "isOccluded", it)
+ }
}
scope.launch {
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 1b7da5b65a03..3c0ec350c5c5 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
@@ -78,6 +78,10 @@ constructor(
val occludedToLockscreenTransition: Flow<TransitionStep> =
repository.transition(OCCLUDED, LOCKSCREEN)
+ /** PRIMARY_BOUNCER->GONE transition information. */
+ val primaryBouncerToGoneTransition: Flow<TransitionStep> =
+ repository.transition(PRIMARY_BOUNCER, GONE)
+
/**
* AOD<->LOCKSCREEN transition information, mapped to dozeAmount range of AOD (1f) <->
* Lockscreen (0f).
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
index 6610983a6ff6..95d38b1fdd82 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
@@ -16,16 +16,22 @@
package com.android.systemui.keyguard.domain.interactor
+import android.content.Context
import android.content.res.ColorStateList
import android.hardware.biometrics.BiometricSourceType
import android.os.Handler
import android.os.Trace
import android.os.UserHandle
import android.os.UserManager
+import android.util.Log
import android.view.View
+import com.android.keyguard.KeyguardConstants
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.settingslib.Utils
import com.android.systemui.DejankUtils
+import com.android.systemui.R
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
@@ -34,7 +40,6 @@ import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.shared.system.SysUiStatsLog
import com.android.systemui.statusbar.phone.KeyguardBypassController
@@ -62,8 +67,9 @@ constructor(
private val primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor,
private val falsingCollector: FalsingCollector,
private val dismissCallbackRegistry: DismissCallbackRegistry,
+ private val context: Context,
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
keyguardBypassController: KeyguardBypassController,
- keyguardUpdateMonitor: KeyguardUpdateMonitor,
) {
/** Whether we want to wait for face auth. */
private val primaryBouncerFaceDelay =
@@ -77,24 +83,21 @@ constructor(
/** Runnable to show the primary bouncer. */
val showRunnable = Runnable {
- repository.setPrimaryVisible(true)
- repository.setPrimaryShow(
- KeyguardBouncerModel(
- promptReason = repository.bouncerPromptReason ?: 0,
- errorMessage = repository.bouncerErrorMessage,
- expansionAmount = repository.panelExpansionAmount.value
+ repository.setPrimaryShow(true)
+ primaryBouncerView.delegate?.showPromptReason(repository.bouncerPromptReason)
+ (repository.bouncerErrorMessage as? String)?.let {
+ repository.setShowMessage(
+ BouncerShowMessageModel(message = it, Utils.getColorError(context))
)
- )
+ }
repository.setPrimaryShowingSoon(false)
primaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.VISIBLE)
}
val keyguardAuthenticated: Flow<Boolean> = repository.keyguardAuthenticated.filterNotNull()
- val screenTurnedOff: Flow<Unit> = repository.onScreenTurnedOff.filter { it }.map {}
- val show: Flow<KeyguardBouncerModel> = repository.primaryBouncerShow.filterNotNull()
- val hide: Flow<Unit> = repository.primaryBouncerHide.filter { it }.map {}
+ val show: Flow<Unit> = repository.primaryBouncerShow.filter { it }.map {}
+ val hide: Flow<Unit> = repository.primaryBouncerShow.filter { !it }.map {}
val startingToHide: Flow<Unit> = repository.primaryBouncerStartingToHide.filter { it }.map {}
- val isVisible: Flow<Boolean> = repository.primaryBouncerVisible
val isBackButtonEnabled: Flow<Boolean> = repository.isBackButtonEnabled.filterNotNull()
val showMessage: Flow<BouncerShowMessageModel> = repository.showMessage.filterNotNull()
val startingDisappearAnimation: Flow<Runnable> =
@@ -104,10 +107,11 @@ constructor(
val panelExpansionAmount: Flow<Float> = repository.panelExpansionAmount
/** 0f = bouncer fully hidden. 1f = bouncer fully visible. */
val bouncerExpansion: Flow<Float> =
- combine(repository.panelExpansionAmount, repository.primaryBouncerVisible) {
- panelExpansion,
- primaryBouncerVisible ->
- if (primaryBouncerVisible) {
+ combine(
+ repository.panelExpansionAmount,
+ repository.primaryBouncerShow
+ ) { panelExpansion, primaryBouncerIsShowing ->
+ if (primaryBouncerIsShowing) {
1f - panelExpansion
} else {
0f
@@ -115,6 +119,26 @@ constructor(
}
/** Allow for interaction when just about fully visible */
val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
+ val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
+
+ /** This callback needs to be a class field so it does not get garbage collected. */
+ val keyguardUpdateMonitorCallback =
+ object : KeyguardUpdateMonitorCallback() {
+ override fun onBiometricRunningStateChanged(
+ running: Boolean,
+ biometricSourceType: BiometricSourceType?
+ ) {
+ updateSideFpsVisibility()
+ }
+
+ override fun onStrongAuthStateChanged(userId: Int) {
+ updateSideFpsVisibility()
+ }
+ }
+
+ init {
+ keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
+ }
// TODO(b/243685699): Move isScrimmed logic to data layer.
// TODO(b/243695312): Encapsulate all of the show logic for the bouncer.
@@ -122,16 +146,14 @@ constructor(
@JvmOverloads
fun show(isScrimmed: Boolean) {
// Reset some states as we show the bouncer.
- repository.setOnScreenTurnedOff(false)
repository.setKeyguardAuthenticated(null)
- repository.setPrimaryHide(false)
repository.setPrimaryStartingToHide(false)
val resumeBouncer =
- (repository.primaryBouncerVisible.value ||
- repository.primaryBouncerShowingSoon.value) && needsFullscreenBouncer()
+ (isBouncerShowing() || repository.primaryBouncerShowingSoon.value) &&
+ needsFullscreenBouncer()
- if (!resumeBouncer && repository.primaryBouncerShow.value != null) {
+ if (!resumeBouncer && isBouncerShowing()) {
// If bouncer is visible, the bouncer is already showing.
return
}
@@ -184,9 +206,7 @@ constructor(
keyguardStateController.notifyPrimaryBouncerShowing(false /* showing */)
cancelShowRunnable()
repository.setPrimaryShowingSoon(false)
- repository.setPrimaryVisible(false)
- repository.setPrimaryHide(true)
- repository.setPrimaryShow(null)
+ repository.setPrimaryShow(false)
primaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.INVISIBLE)
Trace.endSection()
}
@@ -262,11 +282,6 @@ constructor(
repository.setKeyguardAuthenticated(strongAuth)
}
- /** Tell the bouncer the screen has turned off. */
- fun onScreenTurnedOff() {
- repository.setOnScreenTurnedOff(true)
- }
-
/** Update the position of the bouncer when showing. */
fun setKeyguardPosition(position: Float) {
repository.setKeyguardPosition(position)
@@ -301,10 +316,37 @@ constructor(
repository.setPrimaryStartDisappearAnimation(finishRunnable)
}
+ /** Determine whether to show the side fps animation. */
+ fun updateSideFpsVisibility() {
+ val sfpsEnabled: Boolean =
+ context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)
+ val fpsDetectionRunning: Boolean = keyguardUpdateMonitor.isFingerprintDetectionRunning
+ val isUnlockingWithFpAllowed: Boolean =
+ keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed
+ val toShow =
+ (isBouncerShowing() &&
+ sfpsEnabled &&
+ fpsDetectionRunning &&
+ isUnlockingWithFpAllowed &&
+ !isAnimatingAway())
+
+ if (KeyguardConstants.DEBUG) {
+ Log.d(
+ TAG,
+ ("sideFpsToShow=$toShow\n" +
+ "isBouncerShowing=${isBouncerShowing()}\n" +
+ "configEnabled=$sfpsEnabled\n" +
+ "fpsDetectionRunning=$fpsDetectionRunning\n" +
+ "isUnlockingWithFpAllowed=$isUnlockingWithFpAllowed\n" +
+ "isAnimatingAway=${isAnimatingAway()}")
+ )
+ }
+ repository.setSideFpsShowing(toShow)
+ }
+
/** Returns whether bouncer is fully showing. */
fun isFullyShowing(): Boolean {
- return (repository.primaryBouncerShowingSoon.value ||
- repository.primaryBouncerVisible.value) &&
+ return (repository.primaryBouncerShowingSoon.value || isBouncerShowing()) &&
repository.panelExpansionAmount.value == KeyguardBouncerConstants.EXPANSION_VISIBLE &&
repository.primaryBouncerStartingDisappearAnimation.value == null
}
@@ -331,6 +373,11 @@ constructor(
return primaryBouncerView.delegate?.willDismissWithActions() == true
}
+ /** Will the dismissal run from the keyguard layout (instead of from bouncer) */
+ fun willRunDismissFromKeyguard(): Boolean {
+ return primaryBouncerView.delegate?.willRunDismissFromKeyguard() == true
+ }
+
/** Returns whether the bouncer should be full screen. */
private fun needsFullscreenBouncer(): Boolean {
val mode: KeyguardSecurityModel.SecurityMode =
@@ -344,4 +391,12 @@ constructor(
DejankUtils.removeCallbacks(showRunnable)
mainHandler.removeCallbacks(showRunnable)
}
+
+ private fun isBouncerShowing(): Boolean {
+ return repository.primaryBouncerShow.value
+ }
+
+ companion object {
+ private const val TAG = "PrimaryBouncerInteractor"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt
new file mode 100644
index 000000000000..fff7cfe1d6a3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.shared.model
+
+import com.android.systemui.statusbar.policy.DevicePostureController
+
+/** Represents the possible posture states of the device. */
+enum class DevicePosture {
+ UNKNOWN,
+ CLOSED,
+ HALF_OPENED,
+ OPENED,
+ FLIPPED;
+
+ companion object {
+ fun toPosture(@DevicePostureController.DevicePostureInt posture: Int): DevicePosture {
+ return when (posture) {
+ DevicePostureController.DEVICE_POSTURE_CLOSED -> CLOSED
+ DevicePostureController.DEVICE_POSTURE_HALF_OPENED -> HALF_OPENED
+ DevicePostureController.DEVICE_POSTURE_OPENED -> OPENED
+ DevicePostureController.DEVICE_POSTURE_FLIPPED -> FLIPPED
+ DevicePostureController.DEVICE_POSTURE_UNKNOWN -> UNKNOWN
+ else -> UNKNOWN
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBouncerModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ScrimAlpha.kt
index ad783da7f304..1db77336109e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBouncerModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ScrimAlpha.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,12 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License
*/
-
package com.android.systemui.keyguard.shared.model
-/** Models the state of the lock-screen bouncer */
-data class KeyguardBouncerModel(
- val promptReason: Int = 0,
- val errorMessage: CharSequence? = null,
- val expansionAmount: Float = 0f,
+/** Alpha values for scrim updates */
+data class ScrimAlpha(
+ val frontAlpha: Float = 0f,
+ val behindAlpha: Float = 0f,
+ val notificationsAlpha: Float = 0f,
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
index ca1e27c9d19c..38b9d508f81c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
@@ -47,6 +47,7 @@ class KeyguardTransitionAnimationFlow(
duration: Duration,
onStep: (Float) -> Float,
startTime: Duration = 0.milliseconds,
+ onStart: (() -> Unit)? = null,
onCancel: (() -> Float)? = null,
onFinish: (() -> Float)? = null,
interpolator: Interpolator = LINEAR,
@@ -73,6 +74,7 @@ class KeyguardTransitionAnimationFlow(
// the ViewModels of the last update
STARTED -> {
isComplete = false
+ onStart?.invoke()
max(0f, min(1f, value))
}
// Always send a final value of 1. Because of rounding, [value] may never be
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
index ab009f4a6a66..2a9060f6db47 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
@@ -342,7 +342,13 @@ object KeyguardBottomAreaViewBinder {
if (viewModel.isClickable) {
if (viewModel.useLongPress) {
view.setOnTouchListener(
- OnTouchListener(view, viewModel, messageDisplayer, vibratorHelper)
+ OnTouchListener(
+ view,
+ viewModel,
+ messageDisplayer,
+ vibratorHelper,
+ falsingManager,
+ )
)
} else {
view.setOnClickListener(OnClickListener(viewModel, checkNotNull(falsingManager)))
@@ -371,6 +377,7 @@ object KeyguardBottomAreaViewBinder {
private val viewModel: KeyguardQuickAffordanceViewModel,
private val messageDisplayer: (Int) -> Unit,
private val vibratorHelper: VibratorHelper?,
+ private val falsingManager: FalsingManager?,
) : View.OnTouchListener {
private val longPressDurationMs = ViewConfiguration.getLongPressTimeout().toLong()
@@ -395,7 +402,14 @@ object KeyguardBottomAreaViewBinder {
.scaleY(PRESSED_SCALE)
.setDuration(longPressDurationMs)
.withEndAction {
- dispatchClick(viewModel.configKey)
+ if (
+ falsingManager
+ ?.isFalseLongTap(
+ FalsingManager.MODERATE_PENALTY
+ ) == false
+ ) {
+ dispatchClick(viewModel.configKey)
+ }
cancel()
}
}
@@ -421,7 +435,8 @@ object KeyguardBottomAreaViewBinder {
// the pointer performs a click.
if (
viewModel.configKey != null &&
- distanceMoved(event) <= ViewConfiguration.getTouchSlop()
+ distanceMoved(event) <= ViewConfiguration.getTouchSlop() &&
+ falsingManager?.isFalseTap(FalsingManager.NO_PENALTY) == false
) {
dispatchClick(viewModel.configKey)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
index 56f911f8b1da..d7167845419b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
@@ -27,13 +27,14 @@ import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardSecurityView
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.dagger.KeyguardBouncerComponent
-import com.android.settingslib.Utils
import com.android.systemui.keyguard.data.BouncerViewDelegate
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.ActivityStarter
import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
@@ -43,6 +44,7 @@ object KeyguardBouncerViewBinder {
fun bind(
view: ViewGroup,
viewModel: KeyguardBouncerViewModel,
+ primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
componentFactory: KeyguardBouncerComponent.Factory
) {
// Builds the KeyguardSecurityContainerController from bouncer view group.
@@ -94,6 +96,14 @@ object KeyguardBouncerViewBinder {
override fun willDismissWithActions(): Boolean {
return securityContainerController.hasDismissActions()
}
+
+ override fun willRunDismissFromKeyguard(): Boolean {
+ return securityContainerController.willRunDismissFromKeyguard()
+ }
+
+ override fun showPromptReason(reason: Int) {
+ securityContainerController.showPromptReason(reason)
+ }
}
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.CREATED) {
@@ -102,14 +112,11 @@ object KeyguardBouncerViewBinder {
launch {
viewModel.show.collect {
// Reset Security Container entirely.
+ view.visibility = View.VISIBLE
+ securityContainerController.onBouncerVisibilityChanged(
+ /* isVisible= */ true
+ )
securityContainerController.reinflateViewFlipper()
- securityContainerController.showPromptReason(it.promptReason)
- it.errorMessage?.let { errorMessage ->
- securityContainerController.showMessage(
- errorMessage,
- Utils.getColorError(view.context)
- )
- }
securityContainerController.showPrimarySecurityScreen(
/* turningOff= */ false
)
@@ -120,9 +127,13 @@ object KeyguardBouncerViewBinder {
launch {
viewModel.hide.collect {
+ view.visibility = View.INVISIBLE
+ securityContainerController.onBouncerVisibilityChanged(
+ /* isVisible= */ false
+ )
securityContainerController.cancelDismissAction()
- securityContainerController.onPause()
securityContainerController.reset()
+ securityContainerController.onPause()
}
}
@@ -145,6 +156,12 @@ object KeyguardBouncerViewBinder {
}
launch {
+ primaryBouncerToGoneTransitionViewModel.bouncerAlpha.collect { alpha ->
+ securityContainerController.setAlpha(alpha)
+ }
+ }
+
+ launch {
viewModel.bouncerExpansionAmount
.filter { it == EXPANSION_VISIBLE }
.collect {
@@ -154,14 +171,6 @@ object KeyguardBouncerViewBinder {
}
launch {
- viewModel.isBouncerVisible.collect { isVisible ->
- val visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
- view.visibility = visibility
- securityContainerController.onBouncerVisibilityChanged(visibility)
- }
- }
-
- launch {
viewModel.isInteractable.collect { isInteractable ->
securityContainerController.setInteractable(isInteractable)
}
@@ -204,10 +213,14 @@ object KeyguardBouncerViewBinder {
}
launch {
- viewModel.screenTurnedOff.collect {
- if (view.visibility == View.VISIBLE) {
- securityContainerController.onPause()
- }
+ viewModel.shouldUpdateSideFps.collect {
+ viewModel.updateSideFpsVisibility()
+ }
+ }
+
+ launch {
+ viewModel.sideFpsShowing.collect {
+ securityContainerController.updateSideFpsVisibility(it)
}
}
awaitCancellation()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
index ef3f242a39a9..86717537efd3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
@@ -34,7 +34,7 @@ object KeyguardLongPressViewBinder {
* @param viewModel The view-model that models the UI state.
* @param onSingleTap A callback to invoke when the system decides that there was a single tap.
* @param falsingManager [FalsingManager] for making sure the long-press didn't just happen in
- * the user's pocket.
+ * the user's pocket.
*/
@JvmStatic
fun bind(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
index 50722d5c68f8..6d958824f78c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
@@ -26,18 +26,21 @@ import android.util.ArrayMap
import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.shared.quickaffordance.shared.model.KeyguardQuickAffordancePreviewConstants
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
@SysUISingleton
class KeyguardRemotePreviewManager
@Inject
constructor(
private val previewRendererFactory: KeyguardPreviewRendererFactory,
+ @Application private val applicationScope: CoroutineScope,
@Main private val mainDispatcher: CoroutineDispatcher,
@Background private val backgroundHandler: Handler,
) {
@@ -55,7 +58,13 @@ constructor(
// Destroy any previous renderer associated with this token.
activePreviews[renderer.hostToken]?.let { destroyObserver(it) }
- observer = PreviewLifecycleObserver(renderer, mainDispatcher, ::destroyObserver)
+ observer =
+ PreviewLifecycleObserver(
+ renderer,
+ applicationScope,
+ mainDispatcher,
+ ::destroyObserver,
+ )
activePreviews[renderer.hostToken] = observer
renderer.render()
renderer.hostToken?.linkToDeath(observer, 0)
@@ -92,13 +101,18 @@ constructor(
private class PreviewLifecycleObserver(
private val renderer: KeyguardPreviewRenderer,
+ private val scope: CoroutineScope,
private val mainDispatcher: CoroutineDispatcher,
private val requestDestruction: (PreviewLifecycleObserver) -> Unit,
) : Handler.Callback, IBinder.DeathRecipient {
- private var isDestroyed = false
+ private var isDestroyedOrDestroying = false
override fun handleMessage(message: Message): Boolean {
+ if (isDestroyedOrDestroying) {
+ return true
+ }
+
when (message.what) {
KeyguardQuickAffordancePreviewConstants.MESSAGE_ID_SLOT_SELECTED -> {
message.data
@@ -118,14 +132,14 @@ constructor(
}
fun onDestroy(): IBinder? {
- if (isDestroyed) {
+ if (isDestroyedOrDestroying) {
return null
}
- isDestroyed = true
+ isDestroyedOrDestroying = true
val hostToken = renderer.hostToken
hostToken?.unlinkToDeath(this, 0)
- runBlocking(mainDispatcher) { renderer.destroy() }
+ scope.launch(mainDispatcher) { renderer.destroy() }
return hostToken
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
index 1e3b60c27d84..ab9e6a4ce045 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
@@ -135,7 +135,7 @@ constructor(
*
* @param initiallySelectedSlotId The ID of the initial slot to render as the selected one.
* @param shouldHighlightSelectedAffordance Whether the selected quick affordance should be
- * highlighted (while all others are dimmed to make the selected one stand out).
+ * highlighted (while all others are dimmed to make the selected one stand out).
*/
fun enablePreviewMode(
initiallySelectedSlotId: String?,
@@ -187,6 +187,7 @@ constructor(
previewMode.isInPreviewMode &&
previewMode.shouldHighlightSelectedAffordance &&
!isSelected,
+ forceInactive = previewMode.isInPreviewMode
)
}
.distinctUntilChanged()
@@ -198,6 +199,7 @@ constructor(
isClickable: Boolean,
isSelected: Boolean,
isDimmed: Boolean,
+ forceInactive: Boolean,
): KeyguardQuickAffordanceViewModel {
return when (this) {
is KeyguardQuickAffordanceModel.Visible ->
@@ -213,7 +215,7 @@ constructor(
)
},
isClickable = isClickable,
- isActivated = activationState is ActivationState.Active,
+ isActivated = !forceInactive && activationState is ActivationState.Active,
isSelected = isSelected,
useLongPress = quickAffordanceInteractor.useLongPress,
isDimmed = isDimmed,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
index b8b3a8e5db20..68910c65e508 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -21,10 +21,11 @@ import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.BouncerViewDelegate
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
/** Models UI state for the lock screen bouncer; handles user input. */
class KeyguardBouncerViewModel
@@ -36,14 +37,11 @@ constructor(
/** Observe on bouncer expansion amount. */
val bouncerExpansionAmount: Flow<Float> = interactor.panelExpansionAmount
- /** Observe on bouncer visibility. */
- val isBouncerVisible: Flow<Boolean> = interactor.isVisible
-
/** Can the user interact with the view? */
val isInteractable: Flow<Boolean> = interactor.isInteractable
/** Observe whether bouncer is showing. */
- val show: Flow<KeyguardBouncerModel> = interactor.show
+ val show: Flow<Unit> = interactor.show
/** Observe whether bouncer is hiding. */
val hide: Flow<Unit> = interactor.hide
@@ -66,8 +64,16 @@ constructor(
/** Observe whether keyguard is authenticated already. */
val keyguardAuthenticated: Flow<Boolean> = interactor.keyguardAuthenticated
- /** Observe whether screen is turned off. */
- val screenTurnedOff: Flow<Unit> = interactor.screenTurnedOff
+ /** Observe whether the side fps is showing. */
+ val sideFpsShowing: Flow<Boolean> = interactor.sideFpsShowing
+
+ /** Observe whether we should update fps is showing. */
+ val shouldUpdateSideFps: Flow<Unit> =
+ merge(
+ interactor.startingToHide,
+ interactor.show,
+ interactor.startingDisappearAnimation.filterNotNull().map {}
+ )
/** Observe whether we want to update resources. */
fun notifyUpdateResources() {
@@ -84,6 +90,10 @@ constructor(
interactor.onMessageShown()
}
+ fun updateSideFpsVisibility() {
+ interactor.updateSideFpsVisibility()
+ }
+
/** Observe whether back button is enabled. */
fun observeOnIsBackButtonEnabled(systemUiVisibility: () -> Int): Flow<Int> {
return interactor.isBackButtonEnabled.map { enabled ->
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
new file mode 100644
index 000000000000..b23247c30256
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
@@ -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 com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_GONE_DURATION
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.keyguard.shared.model.ScrimAlpha
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+/**
+ * Breaks down PRIMARY_BOUNCER->GONE transition into discrete steps for corresponding views to
+ * consume.
+ */
+@SysUISingleton
+class PrimaryBouncerToGoneTransitionViewModel
+@Inject
+constructor(
+ private val interactor: KeyguardTransitionInteractor,
+ private val statusBarStateController: SysuiStatusBarStateController,
+ private val primaryBouncerInteractor: PrimaryBouncerInteractor,
+) {
+ private val transitionAnimation =
+ KeyguardTransitionAnimationFlow(
+ transitionDuration = TO_GONE_DURATION,
+ transitionFlow = interactor.primaryBouncerToGoneTransition,
+ )
+
+ private var leaveShadeOpen: Boolean = false
+ private var willRunDismissFromKeyguard: Boolean = false
+
+ /** Bouncer container alpha */
+ val bouncerAlpha: Flow<Float> =
+ transitionAnimation.createFlow(
+ duration = 200.milliseconds,
+ onStart = {
+ willRunDismissFromKeyguard = primaryBouncerInteractor.willRunDismissFromKeyguard()
+ },
+ onStep = {
+ if (willRunDismissFromKeyguard) {
+ 0f
+ } else {
+ 1f - it
+ }
+ },
+ )
+
+ /** Scrim alpha values */
+ val scrimAlpha: Flow<ScrimAlpha> =
+ transitionAnimation
+ .createFlow(
+ duration = TO_GONE_DURATION,
+ interpolator = EMPHASIZED_ACCELERATE,
+ onStart = {
+ leaveShadeOpen = statusBarStateController.leaveOpenOnKeyguardHide()
+ willRunDismissFromKeyguard =
+ primaryBouncerInteractor.willRunDismissFromKeyguard()
+ },
+ onStep = { 1f - it },
+ )
+ .map {
+ if (willRunDismissFromKeyguard) {
+ ScrimAlpha(
+ notificationsAlpha = 1f,
+ )
+ } else if (leaveShadeOpen) {
+ ScrimAlpha(
+ behindAlpha = 1f,
+ notificationsAlpha = 1f,
+ )
+ } else {
+ ScrimAlpha(behindAlpha = it)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
index d69ac7fe035d..34a67403fc84 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
@@ -47,13 +47,13 @@ import kotlinx.coroutines.launch
* fresh one.
*
* @param coroutineContext An optional [CoroutineContext] to replace the dispatcher [block] is
- * invoked on.
+ * invoked on.
* @param block The block of code that should be run when the view becomes attached. It can end up
- * being invoked multiple times if the view is reattached after being detached.
+ * being invoked multiple times if the view is reattached after being detached.
* @return A [DisposableHandle] to invoke when the caller of the function destroys its [View] and is
- * no longer interested in the [block] being run the next time its attached. Calling this is an
- * optional optimization as the logic will be properly cleaned up and destroyed each time the view
- * is detached. Using this is not *thread-safe* and should only be used on the main thread.
+ * no longer interested in the [block] being run the next time its attached. Calling this is an
+ * optional optimization as the logic will be properly cleaned up and destroyed each time the view
+ * is detached. Using this is not *thread-safe* and should only be used on the main thread.
*/
@MainThread
fun View.repeatWhenAttached(
@@ -125,7 +125,6 @@ private fun createLifecycleOwnerAndRun(
* The implementation requires the caller to call [onCreate] and [onDestroy] when the view is
* attached to or detached from a view hierarchy. After [onCreate] and before [onDestroy] is called,
* the implementation monitors window state in the following way
- *
* * If the window is not visible, we are in the [Lifecycle.State.CREATED] state
* * If the window is visible but not focused, we are in the [Lifecycle.State.STARTED] state
* * If the window is visible and focused, we are in the [Lifecycle.State.RESUMED] state
diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
index f7349a2a7ae6..647e3a15ba2f 100644
--- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
@@ -16,7 +16,6 @@ private const val TAG = "KeyguardFaceAuthManagerLog"
* Helper class for logging for [com.android.keyguard.faceauth.KeyguardFaceAuthManager]
*
* To enable logcat echoing for an entire buffer:
- *
* ```
* adb shell settings put global systemui/buffer/KeyguardFaceAuthManagerLog <logLevel>
*
diff --git a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
index 5acaa46c25d6..edc278d1ae4f 100644
--- a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
@@ -33,7 +33,6 @@ private const val TAG = "ScreenDecorationsLog"
* Helper class for logging for [com.android.systemui.ScreenDecorations]
*
* To enable logcat echoing for an entire buffer:
- *
* ```
* adb shell settings put global systemui/buffer/ScreenDecorationsLog <logLevel>
*
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/DeviceStateAutoRotationLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/DeviceStateAutoRotationLog.java
new file mode 100644
index 000000000000..beb725e61e4a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/DeviceStateAutoRotationLog.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface DeviceStateAutoRotationLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 817de7976352..98b6d70317b8 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -62,6 +62,15 @@ public class LogModule {
return factory.create("NotifLog", maxSize, false /* systrace */);
}
+ /** Provides a logging buffer for all logs related to notifications on the lockscreen. */
+ @Provides
+ @SysUISingleton
+ @NotificationLockscreenLog
+ public static LogBuffer provideNotificationLockScreenLogBuffer(
+ LogBufferFactory factory) {
+ return factory.create("NotifLockscreenLog", 50, false /* systrace */);
+ }
+
/** Provides a logging buffer for logs related to heads up presentation of notifications. */
@Provides
@SysUISingleton
@@ -361,6 +370,16 @@ public class LogModule {
}
/**
+ * Provides a {@link LogBuffer} for Device State Auto-Rotation logs.
+ */
+ @Provides
+ @SysUISingleton
+ @DeviceStateAutoRotationLog
+ public static LogBuffer provideDeviceStateAutoRotationLogBuffer(LogBufferFactory factory) {
+ return factory.create("DeviceStateAutoRotationLog", 100);
+ }
+
+ /**
* Provides a {@link LogBuffer} for bluetooth-related logs.
*/
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
new file mode 100644
index 000000000000..a2d381ec90f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
@@ -0,0 +1,33 @@
+/*
+ * 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.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.plugins.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for notification & lockscreen related messages. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface NotificationLockscreenLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt
index 4880f80e7716..b73ddc50f831 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt
@@ -59,6 +59,17 @@ data class TableChange(
int = value
}
+ /** Updates this to store the same value as [change]. */
+ fun updateTo(change: TableChange) {
+ reset(change.timestamp, change.columnPrefix, change.columnName)
+ when (change.type) {
+ DataType.STRING -> set(change.str)
+ DataType.INT -> set(change.int)
+ DataType.BOOLEAN -> set(change.bool)
+ DataType.EMPTY -> {}
+ }
+ }
+
/** Returns true if this object has a change. */
fun hasData(): Boolean {
return columnName.isNotBlank() && type != DataType.EMPTY
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
index 1712dab8aff9..a0f1c959aed6 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -16,20 +16,19 @@
package com.android.systemui.log.table
+import android.os.Trace
import com.android.systemui.Dumpable
import com.android.systemui.plugins.util.RingBuffer
import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import java.text.SimpleDateFormat
import java.util.Locale
-import kotlinx.coroutines.flow.Flow
/**
* A logger that logs changes in table format.
*
* Some parts of System UI maintain a lot of pieces of state at once.
* [com.android.systemui.plugins.log.LogBuffer] allows us to easily log change events:
- *
* - 10-10 10:10:10.456: state2 updated to newVal2
* - 10-10 10:11:00.000: stateN updated to StateN(val1=true, val2=1)
* - 10-10 10:11:02.123: stateN updated to StateN(val1=true, val2=2)
@@ -37,7 +36,6 @@ import kotlinx.coroutines.flow.Flow
* - 10-10 10:11:06.000: stateN updated to StateN(val1=false, val2=3)
*
* However, it can sometimes be more useful to view the state changes in table format:
- *
* - timestamp--------- | state1- | state2- | ... | stateN.val1 | stateN.val2
* - -------------------------------------------------------------------------
* - 10-10 10:10:10.123 | val1--- | val2--- | ... | false------ | 0-----------
@@ -56,23 +54,18 @@ import kotlinx.coroutines.flow.Flow
* individual fields.
*
* How it works:
- *
* 1) Create an instance of this buffer via [TableLogBufferFactory].
- *
* 2) For any states being logged, implement [Diffable]. Implementing [Diffable] allows the state to
- * only log the fields that have *changed* since the previous update, instead of always logging all
- * fields.
- *
+ * only log the fields that have *changed* since the previous update, instead of always logging
+ * all fields.
* 3) Each time a change in a state happens, call [logDiffs]. If your state is emitted using a
- * [Flow], you should use the [logDiffsForTable] extension function to automatically log diffs any
- * time your flow emits a new value.
+ * [Flow], you should use the [logDiffsForTable] extension function to automatically log diffs
+ * any time your flow emits a new value.
*
* When a dump occurs, there will be two dumps:
- *
* 1) The change events under the dumpable name "$name-changes".
- *
* 2) This class will coalesce all the diffs into a table format and log them under the dumpable
- * name "$name-table".
+ * name "$name-table".
*
* @param maxSize the maximum size of the buffer. Must be > 0.
*/
@@ -89,6 +82,19 @@ class TableLogBuffer(
private val buffer = RingBuffer(maxSize) { TableChange() }
+ // Stores the most recently evicted value for each column name (indexed on column name).
+ //
+ // Why it's necessary: Because we use a RingBuffer of a fixed size, it's possible that a column
+ // that's logged infrequently will eventually get pushed out by a different column that's
+ // logged more frequently. Then, that infrequently-logged column isn't present in the RingBuffer
+ // at all and we have no logs that the column ever existed. This is a problem because the
+ // column's information is still relevant, valid, and may be critical to debugging issues.
+ //
+ // Fix: When a change is being evicted from the RingBuffer, we store it in this map (based on
+ // its [TableChange.getName()]. This ensures that we always have at least one value for every
+ // column ever logged. See b/272016422 for more details.
+ private val lastEvictedValues = mutableMapOf<String, TableChange>()
+
// A [TableRowLogger] object, re-used each time [logDiffs] is called.
// (Re-used to avoid object allocation.)
private val tempRow = TableRowLoggerImpl(0, columnPrefix = "", this)
@@ -99,11 +105,10 @@ class TableLogBuffer(
* The [newVal] object's method [Diffable.logDiffs] will be used to fetch the diffs.
*
* @param columnPrefix a prefix that will be applied to every column name that gets logged. This
- * ensures that all the columns related to the same state object will be grouped together in the
- * table.
- *
+ * ensures that all the columns related to the same state object will be grouped together in
+ * the table.
* @throws IllegalArgumentException if [columnPrefix] or column name contain "|". "|" is used as
- * the separator token for parsing, so it can't be present in any part of the column name.
+ * the separator token for parsing, so it can't be present in any part of the column name.
*/
@Synchronized
fun <T : Diffable<T>> logDiffs(columnPrefix: String, prevVal: T, newVal: T) {
@@ -117,7 +122,7 @@ class TableLogBuffer(
* Logs change(s) to the buffer using [rowInitializer].
*
* @param rowInitializer a function that will be called immediately to store relevant data on
- * the row.
+ * the row.
*/
@Synchronized
fun logChange(columnPrefix: String, rowInitializer: (TableRowLogger) -> Unit) {
@@ -146,18 +151,24 @@ class TableLogBuffer(
// timestamps.)
private fun logChange(timestamp: Long, prefix: String, columnName: String, value: String?) {
+ Trace.beginSection("TableLogBuffer#logChange(string)")
val change = obtain(timestamp, prefix, columnName)
change.set(value)
+ Trace.endSection()
}
private fun logChange(timestamp: Long, prefix: String, columnName: String, value: Boolean) {
+ Trace.beginSection("TableLogBuffer#logChange(boolean)")
val change = obtain(timestamp, prefix, columnName)
change.set(value)
+ Trace.endSection()
}
private fun logChange(timestamp: Long, prefix: String, columnName: String, value: Int?) {
+ Trace.beginSection("TableLogBuffer#logChange(int)")
val change = obtain(timestamp, prefix, columnName)
change.set(value)
+ Trace.endSection()
}
// TODO(b/259454430): Add additional change types here.
@@ -166,6 +177,9 @@ class TableLogBuffer(
private fun obtain(timestamp: Long, prefix: String, columnName: String): TableChange {
verifyValidName(prefix, columnName)
val tableChange = buffer.advance()
+ if (tableChange.hasData()) {
+ saveEvictedValue(tableChange)
+ }
tableChange.reset(timestamp, prefix, columnName)
return tableChange
}
@@ -181,10 +195,23 @@ class TableLogBuffer(
}
}
+ private fun saveEvictedValue(change: TableChange) {
+ Trace.beginSection("TableLogBuffer#saveEvictedValue")
+ val name = change.getName()
+ val previouslyEvicted =
+ lastEvictedValues[name] ?: TableChange().also { lastEvictedValues[name] = it }
+ // For recycling purposes, update the existing object in the map with the new information
+ // instead of creating a new object.
+ previouslyEvicted.updateTo(change)
+ Trace.endSection()
+ }
+
@Synchronized
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.println(HEADER_PREFIX + name)
pw.println("version $VERSION")
+
+ lastEvictedValues.values.sortedBy { it.timestamp }.forEach { it.dump(pw) }
for (i in 0 until buffer.size) {
buffer[i].dump(pw)
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index 7ccc43ce62c2..06668d33408d 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -38,7 +38,6 @@ constructor(
*
* @param name a unique table name
* @param maxSize the buffer max size. See [adjustMaxSize]
- *
* @return a new [TableLogBuffer] registered with [DumpManager]
*/
fun create(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
index a057c9f22be3..2509f21242cd 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
@@ -187,6 +187,7 @@ constructor(
/**
* Handle request to change the current position in the media track.
+ *
* @param position Place to seek to in the track.
*/
@AnyThread
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
index dc7a4f18adbc..ae03f27b32cd 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
@@ -52,6 +52,7 @@ data class SmartspaceMediaData(
* Indicates if all the data is valid.
*
* TODO(b/230333302): Make MediaControlPanel more flexible so that we can display fewer than
+ *
* ```
* [NUM_REQUIRED_RECOMMENDATIONS].
* ```
@@ -88,6 +89,8 @@ data class SmartspaceMediaData(
}
}
+/** Key to indicate whether this card should be used to re-show recent media */
+const val EXTRA_KEY_TRIGGER_RESUME = "SHOULD_TRIGGER_RESUME"
/** Key for extras [SmartspaceMediaData.cardAction] indicating why the card was sent */
const val EXTRA_KEY_TRIGGER_SOURCE = "MEDIA_RECOMMENDATION_TRIGGER_SOURCE"
/** Value for [EXTRA_KEY_TRIGGER_SOURCE] when the card is sent on headphone connection */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
index 27f7b9736807..207df6bc4422 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
@@ -23,6 +23,7 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.controls.models.player.MediaData
+import com.android.systemui.media.controls.models.recommendation.EXTRA_KEY_TRIGGER_RESUME
import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.media.controls.util.MediaUiEventLogger
@@ -138,14 +139,23 @@ constructor(
val sorted = userEntries.toSortedMap(compareBy { userEntries.get(it)?.lastActive ?: -1 })
val timeSinceActive = timeSinceActiveForMostRecentMedia(sorted)
var smartspaceMaxAgeMillis = SMARTSPACE_MAX_AGE
- data.cardAction?.let {
- val smartspaceMaxAgeSeconds = it.extras.getLong(RESUMABLE_MEDIA_MAX_AGE_SECONDS_KEY, 0)
+ data.cardAction?.extras?.let {
+ val smartspaceMaxAgeSeconds = it.getLong(RESUMABLE_MEDIA_MAX_AGE_SECONDS_KEY, 0)
if (smartspaceMaxAgeSeconds > 0) {
smartspaceMaxAgeMillis = TimeUnit.SECONDS.toMillis(smartspaceMaxAgeSeconds)
}
}
- val shouldReactivate = !hasActiveMedia() && hasAnyMedia() && data.isActive
+ // Check if smartspace has explicitly specified whether to re-activate resumable media.
+ // The default behavior is to trigger if the smartspace data is active.
+ val shouldTriggerResume =
+ if (data.cardAction?.extras?.containsKey(EXTRA_KEY_TRIGGER_RESUME) == true) {
+ data.cardAction.extras.getBoolean(EXTRA_KEY_TRIGGER_RESUME, true)
+ } else {
+ true
+ }
+ val shouldReactivate =
+ shouldTriggerResume && !hasActiveMedia() && hasAnyMedia() && data.isActive
if (timeSinceActive < smartspaceMaxAgeMillis) {
// It could happen there are existing active media resume cards, then we don't need to
@@ -319,9 +329,8 @@ constructor(
* Return the time since last active for the most-recent media.
*
* @param sortedEntries userEntries sorted from the earliest to the most-recent.
- *
* @return The duration in milliseconds from the most-recent media's last active timestamp to
- * the present. MAX_VALUE will be returned if there is no media.
+ * the present. MAX_VALUE will be returned if there is no media.
*/
private fun timeSinceActiveForMostRecentMedia(
sortedEntries: SortedMap<String, MediaData>
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
index f5558a240a70..525b2fcb8dbc 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
@@ -525,8 +525,8 @@ class MediaDataManager(
* through the internal listener pipeline.
*
* @param immediately indicates should apply the UI changes immediately, otherwise wait until
- * the next refresh-round before UI becomes visible. Should only be true if the update is
- * initiated by user's interaction.
+ * the next refresh-round before UI becomes visible. Should only be true if the update is
+ * initiated by user's interaction.
*/
private fun notifySmartspaceMediaDataRemoved(key: String, immediately: Boolean) {
internalListeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) }
@@ -535,6 +535,7 @@ class MediaDataManager(
/**
* Called whenever the player has been paused or stopped for a while, or swiped from QQS. This
* will make the player not active anymore, hiding it from QQS and Keyguard.
+ *
* @see MediaData.active
*/
internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) {
@@ -665,7 +666,7 @@ class MediaDataManager(
appIntent: PendingIntent,
packageName: String
) {
- if (TextUtils.isEmpty(desc.title)) {
+ if (desc.title.isNullOrBlank()) {
Log.e(TAG, "Description incomplete")
// Delete the placeholder entry
mediaEntries.remove(packageName)
@@ -1023,6 +1024,7 @@ class MediaDataManager(
* @param packageName Package name for the media app
* @param controller MediaController for the current session
* @return a Pair consisting of a list of media actions, and a list of ints representing which
+ *
* ```
* of those actions should be shown in the compact player
* ```
@@ -1126,6 +1128,7 @@ class MediaDataManager(
* [PlaybackState.ACTION_SKIP_TO_NEXT]
* @return
* ```
+ *
* A [MediaAction] with correct values set, or null if the state doesn't support it
*/
private fun getStandardAction(
@@ -1226,6 +1229,7 @@ class MediaDataManager(
}
/**
* Load a bitmap from a URI
+ *
* @param uri the uri to load
* @return bitmap, or null if couldn't be loaded
*/
@@ -1339,10 +1343,9 @@ class MediaDataManager(
fun onNotificationRemoved(key: String) {
Assert.isMainThread()
val removed = mediaEntries.remove(key) ?: return
-
if (keyguardUpdateMonitor.isUserInLockdown(removed.userId)) {
logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId)
- } else if (useMediaResumption && removed.resumeAction != null && removed.isLocalSession()) {
+ } else if (isAbleToResume(removed)) {
convertToResumePlayer(key, removed)
} else if (mediaFlags.isRetainingPlayersEnabled()) {
handlePossibleRemoval(key, removed, notificationRemoved = true)
@@ -1362,6 +1365,14 @@ class MediaDataManager(
handlePossibleRemoval(key, updated)
}
+ private fun isAbleToResume(data: MediaData): Boolean {
+ val isEligibleForResume =
+ data.isLocalSession() ||
+ (mediaFlags.isRemoteResumeAllowed() &&
+ data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
+ return useMediaResumption && data.resumeAction != null && isEligibleForResume
+ }
+
/**
* Convert to resume state if the player is no longer valid and active, then notify listeners
* that the data was updated. Does not convert to resume state if the player is still valid, or
@@ -1384,8 +1395,9 @@ class MediaDataManager(
if (DEBUG) Log.d(TAG, "Session destroyed but using notification actions $key")
mediaEntries.put(key, removed)
notifyMediaDataLoaded(key, key, removed)
- } else if (removed.active) {
- // This player was still active - it didn't last long enough to time out: remove
+ } else if (removed.active && !isAbleToResume(removed)) {
+ // This player was still active - it didn't last long enough to time out,
+ // and its app doesn't normally support resume: remove
if (DEBUG) Log.d(TAG, "Removing still-active player $key")
notifyMediaDataRemoved(key)
logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId)
@@ -1405,6 +1417,13 @@ class MediaDataManager(
/** Set the given [MediaData] as a resume state player and notify listeners */
private fun convertToResumePlayer(key: String, data: MediaData) {
if (DEBUG) Log.d(TAG, "Converting $key to resume")
+ // Resumption controls must have a title.
+ if (data.song.isNullOrBlank()) {
+ Log.e(TAG, "Description incomplete")
+ notifyMediaDataRemoved(key)
+ logger.logMediaRemoved(data.appUid, data.packageName, data.instanceId)
+ return
+ }
// Move to resume key (aka package name) if that key doesn't already exist.
val resumeAction = data.resumeAction?.let { getResumeMediaAction(it) }
val actions = resumeAction?.let { listOf(resumeAction) } ?: emptyList()
@@ -1509,15 +1528,13 @@ class MediaDataManager(
* notification key) or vice versa.
*
* @param immediately indicates should apply the UI changes immediately, otherwise wait
- * until the next refresh-round before UI becomes visible. True by default to take in place
- * immediately.
- *
+ * until the next refresh-round before UI becomes visible. True by default to take in
+ * place immediately.
* @param receivedSmartspaceCardLatency is the latency between headphone connects and sysUI
- * displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace
- * signal.
- *
+ * displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace
+ * signal.
* @param isSsReactivated indicates resume media card is reactivated by Smartspace
- * recommendation signal
+ * recommendation signal
*/
fun onMediaDataLoaded(
key: String,
@@ -1532,8 +1549,8 @@ class MediaDataManager(
* Called whenever there's new Smartspace media data loaded.
*
* @param shouldPrioritize indicates the sorting priority of the Smartspace card. If true,
- * it will be prioritized as the first card. Otherwise, it will show up as the last card as
- * default.
+ * it will be prioritized as the first card. Otherwise, it will show up as the last card
+ * as default.
*/
fun onSmartspaceMediaDataLoaded(
key: String,
@@ -1548,8 +1565,8 @@ class MediaDataManager(
* Called whenever a previously existing Smartspace media data was removed.
*
* @param immediately indicates should apply the UI changes immediately, otherwise wait
- * until the next refresh-round before UI becomes visible. True by default to take in place
- * immediately.
+ * until the next refresh-round before UI becomes visible. True by default to take in
+ * place immediately.
*/
fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean = true) {}
}
@@ -1558,7 +1575,7 @@ class MediaDataManager(
* Converts the pass-in SmartspaceTarget to SmartspaceMediaData
*
* @return An empty SmartspaceMediaData with the valid target Id is returned if the
- * SmartspaceTarget's data is invalid.
+ * SmartspaceTarget's data is invalid.
*/
private fun toSmartspaceMediaData(target: SmartspaceTarget): SmartspaceMediaData {
var dismissIntent: Intent? = null
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
index 6a512be091e1..120704c0582a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
@@ -408,9 +408,9 @@ constructor(
* [LocalMediaManager.DeviceCallback.onAboutToConnectDeviceAdded] for more information.
*
* @property fullMediaDevice a full-fledged [MediaDevice] object representing the device. If
- * non-null, prefer using [fullMediaDevice] over [backupMediaDeviceData].
+ * non-null, prefer using [fullMediaDevice] over [backupMediaDeviceData].
* @property backupMediaDeviceData a backup [MediaDeviceData] object containing the minimum
- * information required to display the device. Only use if [fullMediaDevice] is null.
+ * information required to display the device. Only use if [fullMediaDevice] is null.
*/
private data class AboutToConnectDevice(
val fullMediaDevice: MediaDevice? = null,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
index 878962dc60b4..a1d9214cb215 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
@@ -60,6 +60,7 @@ constructor(
/**
* Callback representing that a media object is now expired:
+ *
* @param key Media control unique identifier
* @param timedOut True when expired for {@code PAUSED_MEDIA_TIMEOUT} for active media,
* ```
@@ -70,6 +71,7 @@ constructor(
/**
* Callback representing that a media object [PlaybackState] has changed.
+ *
* @param key Media control unique identifier
* @param state The new [PlaybackState]
*/
@@ -77,6 +79,7 @@ constructor(
/**
* Callback representing that the [MediaSession] for an active control has been destroyed
+ *
* @param key Media control unique identifier
*/
lateinit var sessionCallback: (String) -> Unit
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
index 2d10b823f784..b0389b50cd7d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
@@ -37,6 +37,7 @@ import com.android.systemui.dump.DumpManager
import com.android.systemui.media.controls.models.player.MediaData
import com.android.systemui.media.controls.pipeline.MediaDataManager
import com.android.systemui.media.controls.pipeline.RESUME_MEDIA_TIMEOUT
+import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.settings.UserTracker
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.Utils
@@ -63,7 +64,8 @@ constructor(
private val tunerService: TunerService,
private val mediaBrowserFactory: ResumeMediaBrowserFactory,
dumpManager: DumpManager,
- private val systemClock: SystemClock
+ private val systemClock: SystemClock,
+ private val mediaFlags: MediaFlags,
) : MediaDataManager.Listener, Dumpable {
private var useMediaResumption: Boolean = Utils.useMediaResumption(context)
@@ -231,8 +233,14 @@ constructor(
mediaBrowser = null
}
// If we don't have a resume action, check if we haven't already
- if (data.resumeAction == null && !data.hasCheckedForResume && data.isLocalSession()) {
+ val isEligibleForResume =
+ data.isLocalSession() ||
+ (mediaFlags.isRemoteResumeAllowed() &&
+ data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
+ if (data.resumeAction == null && !data.hasCheckedForResume && isEligibleForResume) {
// TODO also check for a media button receiver intended for restarting (b/154127084)
+ // Set null action to prevent additional attempts to connect
+ mediaDataManager.setResumeAction(key, null)
Log.d(TAG, "Checking for service component for " + data.packageName)
val pm = context.packageManager
val serviceIntent = Intent(MediaBrowserService.SERVICE_INTERFACE)
@@ -243,9 +251,6 @@ constructor(
backgroundExecutor.execute {
tryUpdateResumptionList(key, inf!!.get(0).componentInfo.componentName)
}
- } else {
- // No service found
- mediaDataManager.setResumeAction(key, null)
}
}
}
@@ -257,8 +262,6 @@ constructor(
*/
private fun tryUpdateResumptionList(key: String, componentName: ComponentName) {
Log.d(TAG, "Testing if we can connect to $componentName")
- // Set null action to prevent additional attempts to connect
- mediaDataManager.setResumeAction(key, null)
mediaBrowser =
mediaBrowserFactory.create(
object : ResumeMediaBrowser.Callback() {
@@ -291,6 +294,7 @@ constructor(
/**
* Add the component to the saved list of media browser services, checking for duplicates and
* removing older components that exceed the maximum limit
+ *
* @param componentName
*/
private fun updateResumptionList(componentName: ComponentName) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
index 3493b2453fd6..d460b5b5d782 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
@@ -85,16 +85,13 @@ public class ResumeMediaBrowser {
* ResumeMediaBrowser#disconnect will be called automatically with this function.
*/
public void findRecentMedia() {
- disconnect();
Bundle rootHints = new Bundle();
rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
- mMediaBrowser = mBrowserFactory.create(
+ MediaBrowser browser = mBrowserFactory.create(
mComponentName,
mConnectionCallback,
rootHints);
- updateMediaController();
- mLogger.logConnection(mComponentName, "findRecentMedia");
- mMediaBrowser.connect();
+ connectBrowser(browser, "findRecentMedia");
}
private final MediaBrowser.SubscriptionCallback mSubscriptionCallback =
@@ -202,6 +199,21 @@ public class ResumeMediaBrowser {
};
/**
+ * Connect using a new media browser. Disconnects the existing browser first, if it exists.
+ * @param browser media browser to connect
+ * @param reason Reason to log for connection
+ */
+ private void connectBrowser(MediaBrowser browser, String reason) {
+ mLogger.logConnection(mComponentName, reason);
+ disconnect();
+ mMediaBrowser = browser;
+ if (browser != null) {
+ browser.connect();
+ }
+ updateMediaController();
+ }
+
+ /**
* Disconnect the media browser. This should be done after callbacks have completed to
* disconnect from the media browser service.
*/
@@ -222,10 +234,9 @@ public class ResumeMediaBrowser {
* getting a media update from the app
*/
public void restart() {
- disconnect();
Bundle rootHints = new Bundle();
rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
- mMediaBrowser = mBrowserFactory.create(mComponentName,
+ MediaBrowser browser = mBrowserFactory.create(mComponentName,
new MediaBrowser.ConnectionCallback() {
@Override
public void onConnected() {
@@ -265,9 +276,7 @@ public class ResumeMediaBrowser {
disconnect();
}
}, rootHints);
- updateMediaController();
- mLogger.logConnection(mComponentName, "restart");
- mMediaBrowser.connect();
+ connectBrowser(browser, "restart");
}
@VisibleForTesting
@@ -305,16 +314,13 @@ public class ResumeMediaBrowser {
* ResumeMediaBrowser#disconnect should be called after this to ensure the connection is closed.
*/
public void testConnection() {
- disconnect();
Bundle rootHints = new Bundle();
rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
- mMediaBrowser = mBrowserFactory.create(
+ MediaBrowser browser = mBrowserFactory.create(
mComponentName,
mConnectionCallback,
rootHints);
- updateMediaController();
- mLogger.logConnection(mComponentName, "testConnection");
- mMediaBrowser.connect();
+ connectBrowser(browser, "testConnection");
}
/** Updates mMediaController based on our current browser values. */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
index 335ce1d3d694..095cf09a6c2c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
@@ -52,10 +52,12 @@ class ResumeMediaBrowserLogger @Inject constructor(@MediaBrowserLog private val
* event.
*
* @param isBrowserConnected true if there's a currently connected
+ *
* ```
* [android.media.browse.MediaBrowser] and false otherwise.
* @param componentName
* ```
+ *
* the component name for the [ResumeMediaBrowser] that triggered this log.
*/
fun logSessionDestroyed(isBrowserConnected: Boolean, componentName: ComponentName) =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
index d2793bca867b..f5cc04331f94 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
@@ -24,10 +24,12 @@ import android.graphics.drawable.Drawable
* and conflicts due to media notifications arriving at any time during an animation. It does this
* in two parts.
* - Exit animations fired as a result of user input are tracked. When these are running, any
+ *
* ```
* bind actions are delayed until the animation completes (and then fired in sequence).
* ```
* - Continuous animations are tracked using their rebind id. Later calls using the same
+ *
* ```
* rebind id will be totally ignored to prevent the continuous animation from restarting.
* ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
index 4827a16d229d..2b42604e7160 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
@@ -201,7 +201,9 @@ internal constructor(
animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorSecondary),
::textSecondaryFromScheme
- ) { textSecondary -> mediaViewHolder.artistText.setTextColor(textSecondary) }
+ ) { textSecondary ->
+ mediaViewHolder.artistText.setTextColor(textSecondary)
+ }
val textTertiary =
animatingColorTransitionFactory(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
index 9f86cd88788b..3669493f4e41 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
@@ -159,6 +159,7 @@ class IlluminationDrawable : Drawable() {
/**
* Cross fade background.
+ *
* @see setTintList
* @see backgroundColor
*/
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index 68d2c5c5f4c4..67d3be4a3ad2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -39,6 +39,7 @@ import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -68,6 +69,7 @@ import com.android.systemui.util.time.SystemClock
import com.android.systemui.util.traceSection
import java.io.PrintWriter
import java.util.TreeMap
+import java.util.concurrent.Executor
import javax.inject.Inject
import javax.inject.Provider
import kotlinx.coroutines.CoroutineScope
@@ -93,7 +95,8 @@ constructor(
private val mediaHostStatesManager: MediaHostStatesManager,
private val activityStarter: ActivityStarter,
private val systemClock: SystemClock,
- @Main executor: DelayableExecutor,
+ @Main private val mainExecutor: DelayableExecutor,
+ @Background private val backgroundExecutor: Executor,
private val mediaManager: MediaDataManager,
configurationController: ConfigurationController,
falsingCollector: FalsingCollector,
@@ -194,7 +197,6 @@ constructor(
private val configListener =
object : ConfigurationController.ConfigurationListener {
- var lastOrientation = -1
override fun onDensityOrFontScaleChanged() {
// System font changes should only happen when UMO is offscreen or a flicker may
@@ -211,13 +213,6 @@ constructor(
override fun onConfigChanged(newConfig: Configuration?) {
if (newConfig == null) return
isRtl = newConfig.layoutDirection == View.LAYOUT_DIRECTION_RTL
- val newOrientation = newConfig.orientation
- if (lastOrientation != newOrientation) {
- // The players actually depend on the orientation possibly, so we have to
- // recreate them (at least on large screen devices)
- lastOrientation = newOrientation
- updatePlayers(recreateMedia = true)
- }
}
override fun onUiModeChanged() {
@@ -256,7 +251,7 @@ constructor(
MediaCarouselScrollHandler(
mediaCarousel,
pageIndicator,
- executor,
+ mainExecutor,
this::onSwipeToDismiss,
this::updatePageIndicatorLocation,
this::updateSeekbarListening,
@@ -618,10 +613,50 @@ constructor(
MediaPlayerData.visiblePlayerKeys()
.elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
if (existingPlayer == null) {
- val newPlayer = mediaControlPanelFactory.get()
- newPlayer.attachPlayer(
- MediaViewHolder.create(LayoutInflater.from(context), mediaContent)
+ setupNewPlayer(key, data, isSsReactivated, curVisibleMediaKey)
+ } else {
+ existingPlayer.bindPlayer(data, key)
+ MediaPlayerData.addMediaPlayer(
+ key,
+ data,
+ existingPlayer,
+ systemClock,
+ isSsReactivated,
+ debugLogger
)
+ val packageName = MediaPlayerData.smartspaceMediaData?.packageName ?: String()
+ // In case of recommendations hits.
+ // Check the playing status of media player and the package name.
+ // To make sure we scroll to the right app's media player.
+ if (
+ isReorderingAllowed ||
+ shouldScrollToKey &&
+ data.isPlaying == true &&
+ packageName == data.packageName
+ ) {
+ reorderAllPlayers(curVisibleMediaKey, key)
+ } else {
+ needsReordering = true
+ }
+ updatePageIndicator()
+ mediaCarouselScrollHandler.onPlayersChanged()
+ mediaFrame.requiresRemeasuring = true
+ }
+ return existingPlayer == null
+ }
+
+ private fun setupNewPlayer(
+ key: String,
+ data: MediaData,
+ isSsReactivated: Boolean,
+ curVisibleMediaKey: MediaPlayerData.MediaSortKey?,
+ ) {
+ backgroundExecutor.execute {
+ val mediaViewHolder = createMediaViewHolderInBg()
+ // Add the new player in the main thread.
+ mainExecutor.execute {
+ val newPlayer = mediaControlPanelFactory.get()
+ newPlayer.attachPlayer(mediaViewHolder)
newPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
val lp =
LinearLayout.LayoutParams(
@@ -651,36 +686,16 @@ constructor(
} else {
needsReordering = true
}
- } else {
- existingPlayer.bindPlayer(data, key)
- MediaPlayerData.addMediaPlayer(
- key,
- data,
- existingPlayer,
- systemClock,
- isSsReactivated,
- debugLogger
- )
- val packageName = MediaPlayerData.smartspaceMediaData?.packageName ?: String()
- // In case of recommendations hits.
- // Check the playing status of media player and the package name.
- // To make sure we scroll to the right app's media player.
- if (
- isReorderingAllowed ||
- shouldScrollToKey &&
- data.isPlaying == true &&
- packageName == data.packageName
- ) {
- reorderAllPlayers(curVisibleMediaKey, key)
- } else {
- needsReordering = true
- }
+ updatePageIndicator()
+ mediaCarouselScrollHandler.onPlayersChanged()
+ mediaFrame.requiresRemeasuring = true
}
- updatePageIndicator()
- mediaCarouselScrollHandler.onPlayersChanged()
- mediaFrame.requiresRemeasuring = true
- return existingPlayer == null
}
+ }
+
+ private fun createMediaViewHolderInBg(): MediaViewHolder {
+ return MediaViewHolder.create(LayoutInflater.from(context), mediaContent)
+ }
private fun addSmartspaceMediaRecommendations(
key: String,
@@ -714,15 +729,14 @@ constructor(
debugLogger.logPotentialMemoryLeak(existingSmartspaceMediaKey)
}
}
-
val newRecs = mediaControlPanelFactory.get()
- newRecs.attachRecommendation(
+ val recommendationViewHolder =
RecommendationViewHolder.create(
LayoutInflater.from(context),
mediaContent,
mediaFlags.isRecommendationCardUpdateEnabled()
)
- )
+ newRecs.attachRecommendation(recommendationViewHolder)
newRecs.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
val lp =
LinearLayout.LayoutParams(
@@ -746,17 +760,6 @@ constructor(
reorderAllPlayers(curVisibleMediaKey)
updatePageIndicator()
mediaFrame.requiresRemeasuring = true
- // Check postcondition: mediaContent should have the same number of children as there
- // are
- // elements in mediaPlayers.
- if (MediaPlayerData.players().size != mediaContent.childCount) {
- Log.e(
- TAG,
- "Size of players list and number of views in carousel are out of sync. " +
- "Players size is ${MediaPlayerData.players().size}. " +
- "View count is ${mediaContent.childCount}."
- )
- }
}
fun removePlayer(
@@ -842,10 +845,12 @@ constructor(
* @param startLocation the start location of our state or -1 if this is directly set
* @param endLocation the ending location of our state.
* @param progress the progress of the transition between startLocation and endlocation. If
+ *
* ```
* this is not a guided transformation, this will be 1.0f
* @param immediately
* ```
+ *
* should this state be applied immediately, canceling all animations?
*/
fun setCurrentState(
@@ -1089,17 +1094,17 @@ constructor(
*
* @param eventId UI event id (e.g. 800 for SMARTSPACE_CARD_SEEN)
* @param instanceId id to uniquely identify a card, e.g. each headphone generates a new
- * instanceId
+ * instanceId
* @param uid uid for the application that media comes from
* @param surfaces list of display surfaces the media card is on (e.g. lockscreen, shade) when
- * the event happened
+ * the event happened
* @param interactedSubcardRank the rank for interacted media item for recommendation card, -1
- * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
+ * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
* @param interactedSubcardCardinality how many media items were shown to the user when there is
- * user interaction
+ * user interaction
* @param rank the rank for media card in the media carousel, starting from 0
* @param receivedLatencyMillis latency in milliseconds for card received events. E.g. latency
- * between headphone connection to sysUI displays media recommendation card
+ * between headphone connection to sysUI displays media recommendation card
* @param isSwipeToDismiss whether is to log swipe-to-dismiss event
*/
fun logSmartspaceCardReported(
@@ -1360,6 +1365,7 @@ internal object MediaPlayerData {
/**
* Removes media player given the key.
+ *
* @param isDismissed determines whether the media player is removed from the carousel.
*/
fun removeMediaPlayer(key: String, isDismissed: Boolean = false) =
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 767706209475..4ddff530e658 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
@@ -31,12 +31,15 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
import android.graphics.BlendMode;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.drawable.Animatable;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
@@ -62,7 +65,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
-import androidx.appcompat.content.res.AppCompatResources;
import androidx.constraintlayout.widget.ConstraintSet;
import com.android.internal.annotations.VisibleForTesting;
@@ -145,6 +147,12 @@ public class MediaControlPanel {
private static final int SMARTSPACE_CARD_CLICK_EVENT = 760;
protected static final int SMARTSPACE_CARD_DISMISS_EVENT = 761;
+ private static final float REC_MEDIA_COVER_SCALE_FACTOR = 1.25f;
+ private static final float MEDIA_SCRIM_START_ALPHA = 0.25f;
+ private static final float MEDIA_REC_SCRIM_START_ALPHA = 0.15f;
+ private static final float MEDIA_PLAYER_SCRIM_END_ALPHA = 0.9f;
+ private static final float MEDIA_REC_SCRIM_END_ALPHA = 1.0f;
+
private static final Intent SETTINGS_INTENT = new Intent(ACTION_MEDIA_CONTROLS_SETTINGS);
// Buttons to show in small player when using semantic actions
@@ -226,7 +234,7 @@ public class MediaControlPanel {
private final BroadcastDialogController mBroadcastDialogController;
private boolean mIsCurrentBroadcastedApp = false;
private boolean mShowBroadcastDialogButton = false;
- private String mSwitchBroadcastApp;
+ private String mCurrentBroadcastApp;
private MultiRippleController mMultiRippleController;
private TurbulenceNoiseController mTurbulenceNoiseController;
private final FeatureFlags mFeatureFlags;
@@ -572,9 +580,8 @@ public class MediaControlPanel {
// TODO(b/233698402): Use the package name instead of app label to avoid the
// unexpected result.
mIsCurrentBroadcastedApp = device != null
- && TextUtils.equals(device.getName(),
- MediaDataUtils.getAppLabel(mContext, mPackageName, mContext.getString(
- R.string.bt_le_audio_broadcast_dialog_unknown_name)));
+ && TextUtils.equals(device.getName(),
+ mContext.getString(R.string.broadcasting_description_is_broadcasting));
useDisabledAlpha = !mIsCurrentBroadcastedApp;
// Always be enabled if the broadcast button is shown
isTapEnabled = true;
@@ -629,8 +636,8 @@ public class MediaControlPanel {
// media output dialog.
if (!mIsCurrentBroadcastedApp) {
mLogger.logOpenBroadcastDialog(mUid, mPackageName, mInstanceId);
- mSwitchBroadcastApp = device.getName().toString();
- mBroadcastDialogController.createBroadcastDialog(mSwitchBroadcastApp,
+ mCurrentBroadcastApp = device.getName().toString();
+ mBroadcastDialogController.createBroadcastDialog(mCurrentBroadcastApp,
mPackageName, true, mMediaViewHolder.getSeamlessButton());
} else {
mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId);
@@ -777,7 +784,7 @@ public class MediaControlPanel {
WallpaperColors wallpaperColors = getWallpaperColor(artworkIcon);
if (wallpaperColors != null) {
mutableColorScheme = new ColorScheme(wallpaperColors, true, Style.CONTENT);
- artwork = addGradientToIcon(artworkIcon, mutableColorScheme, width, height);
+ artwork = addGradientToPlayerAlbum(artworkIcon, mutableColorScheme, width, height);
isArtworkBound = true;
} else {
// If there's no artwork, use colors from the app icon
@@ -867,8 +874,9 @@ public class MediaControlPanel {
Trace.beginAsyncSection(traceName, traceCookie);
// Capture width & height from views in foreground for artwork scaling in background
- int width = mRecommendationViewHolder.getMediaCoverContainers().get(0).getMeasuredWidth();
- int height = mRecommendationViewHolder.getMediaCoverContainers().get(0).getMeasuredHeight();
+ int width = mContext.getResources().getDimensionPixelSize(R.dimen.qs_media_rec_album_width);
+ int height = mContext.getResources().getDimensionPixelSize(
+ R.dimen.qs_media_rec_album_height_expanded);
mBackgroundExecutor.execute(() -> {
// Album art
@@ -878,7 +886,8 @@ public class MediaControlPanel {
WallpaperColors wallpaperColors = getWallpaperColor(artworkIcon);
if (wallpaperColors != null) {
mutableColorScheme = new ColorScheme(wallpaperColors, true, Style.CONTENT);
- artwork = addGradientToIcon(artworkIcon, mutableColorScheme, width, height);
+ artwork = addGradientToRecommendationAlbum(artworkIcon, mutableColorScheme, width,
+ height);
} else {
artwork = new ColorDrawable(Color.TRANSPARENT);
}
@@ -887,6 +896,11 @@ public class MediaControlPanel {
// Bind the artwork drawable to media cover.
ImageView mediaCover =
mRecommendationViewHolder.getMediaCoverItems().get(itemIndex);
+ // Rescale media cover
+ Matrix coverMatrix = new Matrix(mediaCover.getImageMatrix());
+ coverMatrix.postScale(REC_MEDIA_COVER_SCALE_FACTOR, REC_MEDIA_COVER_SCALE_FACTOR,
+ 0.5f * width, 0.5f * height);
+ mediaCover.setImageMatrix(coverMatrix);
mediaCover.setImageDrawable(artwork);
// Set up the app icon.
@@ -908,40 +922,62 @@ public class MediaControlPanel {
// This method should be called from a background thread. WallpaperColors.fromBitmap takes a
// good amount of time. We do that work on the background executor to avoid stalling animations
// on the UI Thread.
- private WallpaperColors getWallpaperColor(Icon artworkIcon) {
+ @VisibleForTesting
+ protected WallpaperColors getWallpaperColor(Icon artworkIcon) {
if (artworkIcon != null) {
if (artworkIcon.getType() == Icon.TYPE_BITMAP
|| artworkIcon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) {
// Avoids extra processing if this is already a valid bitmap
- return WallpaperColors
- .fromBitmap(artworkIcon.getBitmap());
+ Bitmap artworkBitmap = artworkIcon.getBitmap();
+ if (artworkBitmap.isRecycled()) {
+ Log.d(TAG, "Cannot load wallpaper color from a recycled bitmap");
+ return null;
+ }
+ return WallpaperColors.fromBitmap(artworkBitmap);
} else {
Drawable artworkDrawable = artworkIcon.loadDrawable(mContext);
if (artworkDrawable != null) {
- return WallpaperColors
- .fromDrawable(artworkIcon.loadDrawable(mContext));
+ return WallpaperColors.fromDrawable(artworkDrawable);
}
}
}
return null;
}
- private LayerDrawable addGradientToIcon(
- Icon artworkIcon,
- ColorScheme mutableColorScheme,
- int width,
- int height
- ) {
+ @VisibleForTesting
+ protected LayerDrawable addGradientToPlayerAlbum(Icon artworkIcon,
+ ColorScheme mutableColorScheme, int width, int height) {
Drawable albumArt = getScaledBackground(artworkIcon, width, height);
- GradientDrawable gradient = (GradientDrawable) AppCompatResources
- .getDrawable(mContext, R.drawable.qs_media_scrim);
+ GradientDrawable gradient = (GradientDrawable) mContext.getDrawable(
+ R.drawable.qs_media_scrim).mutate();
+ return setupGradientColorOnDrawable(albumArt, gradient, mutableColorScheme,
+ MEDIA_SCRIM_START_ALPHA, MEDIA_PLAYER_SCRIM_END_ALPHA);
+ }
+
+ @VisibleForTesting
+ protected LayerDrawable addGradientToRecommendationAlbum(Icon artworkIcon,
+ ColorScheme mutableColorScheme, int width, int height) {
+ // First try scaling rec card using bitmap drawable.
+ // If returns null, set drawable bounds.
+ Drawable albumArt = getScaledRecommendationCover(artworkIcon, width, height);
+ if (albumArt == null) {
+ albumArt = getScaledBackground(artworkIcon, width, height);
+ }
+ GradientDrawable gradient = (GradientDrawable) mContext.getDrawable(
+ R.drawable.qs_media_rec_scrim).mutate();
+ return setupGradientColorOnDrawable(albumArt, gradient, mutableColorScheme,
+ MEDIA_REC_SCRIM_START_ALPHA, MEDIA_REC_SCRIM_END_ALPHA);
+ }
+
+ private LayerDrawable setupGradientColorOnDrawable(Drawable albumArt, GradientDrawable gradient,
+ ColorScheme mutableColorScheme, float startAlpha, float endAlpha) {
gradient.setColors(new int[] {
ColorUtilKt.getColorWithAlpha(
MediaColorSchemesKt.backgroundStartFromScheme(mutableColorScheme),
- 0.25f),
+ startAlpha),
ColorUtilKt.getColorWithAlpha(
MediaColorSchemesKt.backgroundEndFromScheme(mutableColorScheme),
- 0.9f),
+ endAlpha),
});
return new LayerDrawable(new Drawable[] { albumArt, gradient });
}
@@ -1587,6 +1623,29 @@ public class MediaControlPanel {
}
/**
+ * Scale artwork to fill the background of media covers in recommendation card.
+ */
+ @UiThread
+ private Drawable getScaledRecommendationCover(Icon artworkIcon, int width, int height) {
+ if (width == 0 || height == 0) {
+ return null;
+ }
+ if (artworkIcon != null) {
+ Bitmap bitmap;
+ if (artworkIcon.getType() == Icon.TYPE_BITMAP
+ || artworkIcon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) {
+ Bitmap artworkBitmap = artworkIcon.getBitmap();
+ if (artworkBitmap != null) {
+ bitmap = Bitmap.createScaledBitmap(artworkIcon.getBitmap(), width,
+ height, false);
+ return new BitmapDrawable(mContext.getResources(), bitmap);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
* Get the current media controller
*
* @return the controller
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
index 66f12d6242b0..e10d74db6333 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
@@ -28,7 +28,6 @@ import android.net.Uri
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
-import android.util.Log
import android.util.MathUtils
import android.view.View
import android.view.ViewGroup
@@ -418,8 +417,8 @@ constructor(
* Calculate the alpha of the view when given a cross-fade progress.
*
* @param crossFadeProgress The current cross fade progress. 0.5f means it's just switching
- * between the start and the end location and the content is fully faded, while 0.75f means that
- * we're halfway faded in again in the target state.
+ * between the start and the end location and the content is fully faded, while 0.75f means
+ * that we're halfway faded in again in the target state.
*/
private fun calculateAlphaFromCrossFade(crossFadeProgress: Float): Float {
if (crossFadeProgress <= 0.5f) {
@@ -629,6 +628,7 @@ constructor(
*
* @param forceNoAnimation optional parameter telling the system not to animate
* @param forceStateUpdate optional parameter telling the system to update transition state
+ *
* ```
* even if location did not change
* ```
@@ -639,7 +639,9 @@ constructor(
) =
traceSection("MediaHierarchyManager#updateDesiredLocation") {
val desiredLocation = calculateLocation()
- if (desiredLocation != this.desiredLocation || forceStateUpdate) {
+ if (
+ desiredLocation != this.desiredLocation || forceStateUpdate && !blockLocationChanges
+ ) {
if (this.desiredLocation >= 0 && desiredLocation != this.desiredLocation) {
// Only update previous location when it actually changes
previousLocation = this.desiredLocation
@@ -944,7 +946,7 @@ constructor(
/**
* @return the current transformation progress if we're in a guided transformation and -1
- * otherwise
+ * otherwise
*/
private fun getTransformationProgress(): Float {
if (skipQqsOnExpansion) {
@@ -1055,17 +1057,6 @@ constructor(
// This will either do a full layout pass and remeasure, or it will bypass
// that and directly set the mediaFrame's bounds within the premeasured host.
targetHost.addView(mediaFrame)
-
- if (mediaFrame.childCount > 0) {
- val child = mediaFrame.getChildAt(0)
- if (mediaFrame.height < child.height) {
- Log.wtf(
- TAG,
- "mediaFrame height is too small for child: " +
- "${mediaFrame.height} vs ${child.height}"
- )
- }
- }
}
if (isCrossFadeAnimatorRunning) {
// When cross-fading with an animation, we only notify the media carousel of the
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
index 455b7de3dc0c..be570b4a1119 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
@@ -126,6 +126,7 @@ constructor(
* remeasurings later on.
*
* @param location the location this host name has. Used to identify the host during
+ *
* ```
* transitions.
* ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
index b9b0459ad615..b4724ddebb9a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
@@ -154,9 +154,11 @@ constructor(
return transitionLayout?.translationY ?: 0.0f
}
- /** A callback for RTL config changes */
+ /** A callback for config changes */
private val configurationListener =
object : ConfigurationController.ConfigurationListener {
+ var lastOrientation = -1
+
override fun onConfigChanged(newConfig: Configuration?) {
// Because the TransitionLayout is not always attached (and calculates/caches layout
// results regardless of attach state), we have to force the layoutDirection of the
@@ -169,6 +171,13 @@ constructor(
transitionLayout?.layoutDirection = layoutDirection
refreshState()
}
+ val newOrientation = newConfig.orientation
+ if (lastOrientation != newOrientation) {
+ // Layout dimensions are possibly changing, so we need to update them. (at
+ // least on large screen devices)
+ lastOrientation = newOrientation
+ loadLayoutForType(type)
+ }
}
}
}
@@ -195,13 +204,14 @@ constructor(
* The expanded constraint set used to render a expanded player. If it is modified, make sure to
* call [refreshState]
*/
- val collapsedLayout = ConstraintSet()
-
+ var collapsedLayout = ConstraintSet()
+ @VisibleForTesting set
/**
* The expanded constraint set used to render a collapsed player. If it is modified, make sure
* to call [refreshState]
*/
- val expandedLayout = ConstraintSet()
+ var expandedLayout = ConstraintSet()
+ @VisibleForTesting set
/** Whether the guts are visible for the associated player. */
var isGutsVisible = false
@@ -348,14 +358,17 @@ constructor(
* bottom of UMO reach the bottom of this group It will change to alpha 1.0 when the visible
* bottom of UMO reach the top of the group below e.g.Album title, artist title and play-pause
* button will change alpha together.
+ *
* ```
* And their alpha becomes 1.0 when the visible bottom of UMO reach the top of controls,
* including progress bar, next button, previous button
* ```
+ *
* widgetGroupIds: a group of widgets have same state during UMO is squished,
* ```
* e.g. Album title, artist title and play-pause button
* ```
+ *
* groupEndPosition: the height of UMO, when the height reaches this value,
* ```
* widgets in this group should have 1.0 as alpha
@@ -363,6 +376,7 @@ constructor(
* visible when the height of UMO reaches the top of controls group
* (progress bar, previous button and next button)
* ```
+ *
* squishedViewState: hold the widgetState of each widget, which will be modified
* squishFraction: the squishFraction of UMO
*/
@@ -479,7 +493,7 @@ constructor(
*/
fun attach(transitionLayout: TransitionLayout, type: TYPE) =
traceSection("MediaViewController#attach") {
- updateMediaViewControllerType(type)
+ loadLayoutForType(type)
logger.logMediaLocation("attach $type", currentStartLocation, currentEndLocation)
this.transitionLayout = transitionLayout
layoutController.attach(transitionLayout)
@@ -637,7 +651,7 @@ constructor(
return result
}
- private fun updateMediaViewControllerType(type: TYPE) {
+ private fun loadLayoutForType(type: TYPE) {
this.type = type
// These XML resources contain ConstraintSets that will apply to this player type's layout
@@ -665,7 +679,7 @@ constructor(
*
* @param location Target
* @param locationWhenHidden Location that will be used when the target is not
- * [MediaHost.visible]
+ * [MediaHost.visible]
* @return State require for executing a transition, and also the respective [MediaHost].
*/
private fun obtainViewStateForLocation(@MediaLocation location: Int): TransitionViewState? {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index c3fa76ec9433..9bc66f6c98d0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -61,4 +61,7 @@ class MediaFlags @Inject constructor(private val featureFlags: FeatureFlags) {
/** If true, do not automatically dismiss the recommendation card */
fun isPersistentSsCardEnabled() = featureFlags.isEnabled(Flags.MEDIA_RETAIN_RECOMMENDATIONS)
+
+ /** Check whether we allow remote media to generate resume controls */
+ fun isRemoteResumeAllowed() = featureFlags.isEnabled(Flags.MEDIA_REMOTE_RESUME)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
index e35575bfc184..b5b1f0ffe23d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
@@ -23,8 +23,6 @@ import android.util.Log;
import com.android.systemui.CoreStartable;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.statusbar.CommandQueue;
import javax.inject.Inject;
@@ -37,26 +35,19 @@ public class MediaOutputSwitcherDialogUI implements CoreStartable, CommandQueue.
private final CommandQueue mCommandQueue;
private final MediaOutputDialogFactory mMediaOutputDialogFactory;
- private final FeatureFlags mFeatureFlags;
@Inject
public MediaOutputSwitcherDialogUI(
Context context,
CommandQueue commandQueue,
- MediaOutputDialogFactory mediaOutputDialogFactory,
- FeatureFlags featureFlags) {
+ MediaOutputDialogFactory mediaOutputDialogFactory) {
mCommandQueue = commandQueue;
mMediaOutputDialogFactory = mediaOutputDialogFactory;
- mFeatureFlags = featureFlags;
}
@Override
public void start() {
- if (mFeatureFlags.isEnabled(Flags.OUTPUT_SWITCHER_SHOW_API_ENABLED)) {
- mCommandQueue.addCallback(this);
- } else {
- Log.w(TAG, "Show media output switcher is not enabled.");
- }
+ mCommandQueue.addCallback(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
index 720c44a0904b..ee93c3788243 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
@@ -43,7 +43,7 @@ class MediaTttUtils {
*
* @param appPackageName the package name of the app playing the media.
* @param onPackageNotFoundException a function run if a
- * [PackageManager.NameNotFoundException] occurs.
+ * [PackageManager.NameNotFoundException] occurs.
* @param isReceiver indicates whether the icon is displayed in a receiver view.
*/
fun getIconInfoFromPackageName(
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
index 4ff082ad6e06..0b0535df6228 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
@@ -98,7 +98,7 @@ class ReceiverChipRippleView(context: Context?, attrs: AttributeSet?) : RippleVi
// Calculates the actual starting percentage according to ripple shader progress set method.
// Check calculations in [RippleShader.progress]
fun calculateStartingPercentage(newHeight: Float): Float {
- val ratio = rippleShader.currentHeight / newHeight
+ val ratio = rippleShader.rippleSize.currentHeight / newHeight
val remainingPercentage = (1 - ratio).toDouble().pow(1 / 3.toDouble()).toFloat()
return 1 - remainingPercentage
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
index 537dbb93826e..d3efae427cb0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
@@ -23,7 +23,6 @@ import androidx.annotation.StringRes
import com.android.internal.logging.UiEventLogger
import com.android.systemui.R
import com.android.systemui.common.shared.model.Text
-import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS
/**
* A class enumerating all the possible states of the media tap-to-transfer chip on the sender
@@ -34,8 +33,8 @@ import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS
* state should not have the chip be displayed.
* @property transferStatus the transfer status that the chip state represents.
* @property endItem the item that should be displayed in the end section of the chip.
- * @property timeout the amount of time this chip should display on the screen before it times out
- * and disappears.
+ * @property timeoutLength how long the chip should display on the screen before it times out and
+ * disappears.
*/
enum class ChipStateSender(
@StatusBarManager.MediaTransferSenderState val stateInt: Int,
@@ -43,7 +42,7 @@ enum class ChipStateSender(
@StringRes val stringResId: Int?,
val transferStatus: TransferStatus,
val endItem: SenderEndItem?,
- val timeout: Int = DEFAULT_TIMEOUT_MILLIS,
+ val timeoutLength: TimeoutLength = TimeoutLength.DEFAULT,
) {
/**
* A state representing that the two devices are close but not close enough to *start* a cast to
@@ -56,6 +55,9 @@ enum class ChipStateSender(
R.string.media_move_closer_to_start_cast,
transferStatus = TransferStatus.NOT_STARTED,
endItem = null,
+ // Give this view more time in case the loading view takes a bit to come in. (We don't want
+ // this view to disappear and then the loading view to appear quickly afterwards.)
+ timeoutLength = TimeoutLength.LONG,
) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
@@ -75,6 +77,7 @@ enum class ChipStateSender(
R.string.media_move_closer_to_end_cast,
transferStatus = TransferStatus.NOT_STARTED,
endItem = null,
+ timeoutLength = TimeoutLength.LONG,
) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
@@ -92,7 +95,9 @@ enum class ChipStateSender(
R.string.media_transfer_playing_different_device,
transferStatus = TransferStatus.IN_PROGRESS,
endItem = SenderEndItem.Loading,
- timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
+ // Give this view more time in case the succeeded/failed view takes a bit to come in. (We
+ // don't want this view to disappear and then the next view to appear quickly afterwards.)
+ timeoutLength = TimeoutLength.LONG,
) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
@@ -111,7 +116,7 @@ enum class ChipStateSender(
R.string.media_transfer_playing_this_device,
transferStatus = TransferStatus.IN_PROGRESS,
endItem = SenderEndItem.Loading,
- timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
+ timeoutLength = TimeoutLength.LONG,
) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
@@ -325,9 +330,16 @@ sealed class SenderEndItem {
) : SenderEndItem()
}
-// Give the Transfer*Triggered states a longer timeout since those states represent an active
-// process and we should keep the user informed about it as long as possible (but don't allow it to
-// continue indefinitely).
-private const val TRANSFER_TRIGGERED_TIMEOUT_MILLIS = 30000
+/** Represents how long the chip should be visible before it times out. */
+enum class TimeoutLength {
+ /** A default timeout used for temporary displays at the top of the screen. */
+ DEFAULT,
+ /**
+ * A longer timeout. Should be used when the status is pending (e.g. loading), so that the user
+ * remains informed about the process for longer and so that the UI has more time to resolve the
+ * pending state before disappearing.
+ */
+ LONG,
+}
private const val TAG = "ChipStateSender"
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
index 6bb6906a0dfc..c7c72a9cd120 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
@@ -56,6 +56,9 @@ constructor(
private val uiEventLogger: MediaTttSenderUiEventLogger,
) : CoreStartable, Dumpable {
+ // Since the media transfer display is similar to a heads-up notification, use the same timeout.
+ private val defaultTimeout = context.resources.getInteger(R.integer.heads_up_notification_decay)
+
// A map to store current chip state per id.
private var stateMap: MutableMap<String, ChipStateSender> = mutableMapOf()
@@ -165,6 +168,12 @@ constructor(
logger.logPackageNotFound(packageName)
}
+ val timeout =
+ when (chipStateSender.timeoutLength) {
+ TimeoutLength.DEFAULT -> defaultTimeout
+ TimeoutLength.LONG -> 2 * defaultTimeout
+ }
+
return ChipbarInfo(
// Display the app's icon as the start icon
startIcon = icon.toTintedIcon(),
@@ -191,7 +200,7 @@ constructor(
allowSwipeToDismiss = true,
windowTitle = MediaTttUtils.WINDOW_TITLE_SENDER,
wakeReason = MediaTttUtils.WAKE_REASON_SENDER,
- timeoutMs = chipStateSender.timeout,
+ timeoutMs = timeout,
id = routeInfo.id,
priority = ViewPriority.NORMAL,
)
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
index 7a77c476aa11..01398cf81314 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
@@ -70,6 +70,8 @@ constructor(
RECENT_IGNORE_UNAVAILABLE,
userTracker.userId,
backgroundExecutor
- ) { tasks -> continuation.resume(tasks) }
+ ) { tasks ->
+ continuation.resume(tasks)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
index d4991f90a86b..9b9d561b5180 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
@@ -33,7 +33,7 @@ import com.android.systemui.R
import com.android.systemui.mediaprojection.appselector.data.RecentTask
import com.android.systemui.shared.recents.model.ThumbnailData
import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
-import com.android.systemui.shared.recents.utilities.Utilities.isTablet
+import com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen
/**
* Custom view that shows a thumbnail preview of one recent task based on [ThumbnailData].
@@ -150,9 +150,9 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
val displayWidthPx = windowMetrics.bounds.width()
val displayHeightPx = windowMetrics.bounds.height()
val isRtl = layoutDirection == LAYOUT_DIRECTION_RTL
- val isTablet = isTablet(context)
+ val isLargeScreen = isLargeScreen(context)
val taskbarSize =
- if (isTablet) {
+ if (isLargeScreen) {
resources.getDimensionPixelSize(AndroidR.dimen.taskbar_frame_height)
} else {
0
@@ -166,7 +166,7 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
displayWidthPx,
displayHeightPx,
taskbarSize,
- isTablet,
+ isLargeScreen,
currentRotation,
isRtl
)
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
index 88d5eaaff216..9bccb7df4ed0 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
@@ -23,7 +23,8 @@ import android.view.WindowManager
import com.android.internal.R as AndroidR
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorScope
import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener
-import com.android.systemui.shared.recents.utilities.Utilities.isTablet
+import com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen
+import com.android.systemui.shared.system.QuickStepContract
import com.android.systemui.statusbar.policy.CallbackController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
@@ -61,8 +62,15 @@ constructor(
val width = windowMetrics.bounds.width()
var height = maximumWindowHeight
- val isTablet = isTablet(context)
- if (isTablet) {
+ // TODO(b/271410803): Read isTransientTaskbar from Launcher
+ val isLargeScreen = isLargeScreen(context)
+ val isTransientTaskbar =
+ QuickStepContract.isGesturalMode(
+ context.resources.getInteger(
+ com.android.internal.R.integer.config_navBarInteractionMode
+ )
+ )
+ if (isLargeScreen && !isTransientTaskbar) {
val taskbarSize =
context.resources.getDimensionPixelSize(AndroidR.dimen.taskbar_frame_height)
height -= taskbarSize
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
index 1121e160c353..1da8718b111f 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -41,11 +41,17 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Secure;
+import android.util.Log;
+import android.view.IRotationWatcher;
+import android.view.IWallpaperVisibilityListener;
+import android.view.IWindowManager;
import android.view.View;
import android.view.WindowInsets;
+import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
import androidx.annotation.NonNull;
@@ -57,7 +63,9 @@ import com.android.systemui.accessibility.SystemActions;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
@@ -90,6 +98,9 @@ public final class NavBarHelper implements
AccessibilityButtonTargetsObserver.TargetsChangedListener,
OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener,
Dumpable, CommandQueue.Callbacks {
+ private static final String TAG = NavBarHelper.class.getSimpleName();
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
private final AccessibilityManager mAccessibilityManager;
private final Lazy<AssistManager> mAssistManagerLazy;
private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
@@ -98,28 +109,60 @@ public final class NavBarHelper implements
private final SystemActions mSystemActions;
private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
private final AccessibilityButtonTargetsObserver mAccessibilityButtonTargetsObserver;
- private final List<NavbarTaskbarStateUpdater> mA11yEventListeners = new ArrayList<>();
+ private final List<NavbarTaskbarStateUpdater> mStateListeners = new ArrayList<>();
private final Context mContext;
private final CommandQueue mCommandQueue;
private final ContentResolver mContentResolver;
+ private final EdgeBackGestureHandler mEdgeBackGestureHandler;
+ private final IWindowManager mWm;
+ private final int mDefaultDisplayId;
private boolean mAssistantAvailable;
private boolean mLongPressHomeEnabled;
private boolean mAssistantTouchGestureEnabled;
private int mNavBarMode;
private int mA11yButtonState;
+ private int mRotationWatcherRotation;
+ private boolean mTogglingNavbarTaskbar;
+ private boolean mWallpaperVisible;
// Attributes used in NavBarHelper.CurrentSysuiState
private int mWindowStateDisplayId;
private @WindowVisibleState int mWindowState;
- private final ContentObserver mAssistContentObserver = new ContentObserver(
- new Handler(Looper.getMainLooper())) {
+ // Listens for changes to the assistant
+ private final ContentObserver mAssistContentObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange, Uri uri) {
updateAssistantAvailability();
}
};
+ // Listens for changes to the wallpaper visibility
+ private final IWallpaperVisibilityListener mWallpaperVisibilityListener =
+ new IWallpaperVisibilityListener.Stub() {
+ @Override
+ public void onWallpaperVisibilityChanged(boolean visible,
+ int displayId) throws RemoteException {
+ mHandler.post(() -> {
+ mWallpaperVisible = visible;
+ dispatchWallpaperVisibilityChanged(visible, displayId);
+ });
+ }
+ };
+
+ // Listens for changes to display rotation
+ private final IRotationWatcher mRotationWatcher = new IRotationWatcher.Stub() {
+ @Override
+ public void onRotationChanged(final int rotation) {
+ // We need this to be scheduled as early as possible to beat the redrawing of
+ // window in response to the orientation change.
+ mHandler.postAtFrontOfQueue(() -> {
+ mRotationWatcherRotation = rotation;
+ dispatchRotationChanged(rotation);
+ });
+ }
+ };
+
/**
* @param context This is not display specific, then again neither is any of the code in
* this class. Once there's display specific code, we may want to create an
@@ -135,7 +178,10 @@ public final class NavBarHelper implements
Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
KeyguardStateController keyguardStateController,
NavigationModeController navigationModeController,
+ EdgeBackGestureHandler.Factory edgeBackGestureHandlerFactory,
+ IWindowManager wm,
UserTracker userTracker,
+ DisplayTracker displayTracker,
DumpManager dumpManager,
CommandQueue commandQueue) {
mContext = context;
@@ -147,18 +193,36 @@ public final class NavBarHelper implements
mKeyguardStateController = keyguardStateController;
mUserTracker = userTracker;
mSystemActions = systemActions;
- accessibilityManager.addAccessibilityServicesStateChangeListener(this);
mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver;
+ mWm = wm;
+ mDefaultDisplayId = displayTracker.getDefaultDisplayId();
+ mEdgeBackGestureHandler = edgeBackGestureHandlerFactory.create(context);
- mAccessibilityButtonModeObserver.addListener(this);
- mAccessibilityButtonTargetsObserver.addListener(this);
mNavBarMode = navigationModeController.addListener(this);
+ mCommandQueue.addCallback(this);
overviewProxyService.addCallback(this);
dumpManager.registerDumpable(this);
}
- public void init() {
+ /**
+ * Hints to the helper that bars are being replaced, which is a signal to potentially suppress
+ * normal setup/cleanup when no bars are present.
+ */
+ public void setTogglingNavbarTaskbar(boolean togglingNavbarTaskbar) {
+ mTogglingNavbarTaskbar = togglingNavbarTaskbar;
+ }
+
+ /**
+ * Called when the first (non-replacing) bar is registered.
+ */
+ private void setupOnFirstBar() {
+ // Setup accessibility listeners
+ mAccessibilityManager.addAccessibilityServicesStateChangeListener(this);
+ mAccessibilityButtonModeObserver.addListener(this);
+ mAccessibilityButtonTargetsObserver.addListener(this);
+
+ // Setup assistant listener
mContentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
@@ -168,59 +232,114 @@ public final class NavBarHelper implements
mContentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED),
false, mAssistContentObserver, UserHandle.USER_ALL);
- updateAssistantAvailability();
- updateA11yState();
- mCommandQueue.addCallback(this);
+ // Setup display rotation watcher
+ try {
+ mWm.watchRotation(mRotationWatcher, mDefaultDisplayId);
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to register rotation watcher", e);
+ }
+
+ // Setup wallpaper visibility listener
+ try {
+ mWallpaperVisible = mWm.registerWallpaperVisibilityListener(
+ mWallpaperVisibilityListener, mDefaultDisplayId);
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to register wallpaper visibility listener", e);
+ }
+
+ // Attach the back handler only when the first bar is registered
+ mEdgeBackGestureHandler.onNavBarAttached();
}
- public void destroy() {
+ /**
+ * Called after the last (non-replacing) bar is unregistered.
+ */
+ private void cleanupAfterLastBar() {
+ // Clean up accessibility listeners
+ mAccessibilityManager.removeAccessibilityServicesStateChangeListener(this);
+ mAccessibilityButtonModeObserver.removeListener(this);
+ mAccessibilityButtonTargetsObserver.removeListener(this);
+
+ // Clean up assistant listeners
mContentResolver.unregisterContentObserver(mAssistContentObserver);
- mCommandQueue.removeCallback(this);
+
+ // Clean up display rotation watcher
+ try {
+ mWm.removeRotationWatcher(mRotationWatcher);
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to unregister rotation watcher", e);
+ }
+
+ // Clean up wallpaper visibility listener
+ try {
+ mWm.unregisterWallpaperVisibilityListener(mWallpaperVisibilityListener,
+ mDefaultDisplayId);
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to register wallpaper visibility listener", e);
+ }
+
+ // No more bars, detach the back handler for now
+ mEdgeBackGestureHandler.onNavBarDetached();
}
/**
+ * Registers a listener for future updates to the shared navbar/taskbar state.
* @param listener Will immediately get callbacks based on current state
*/
public void registerNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) {
- mA11yEventListeners.add(listener);
- listener.updateAccessibilityServicesState();
- listener.updateAssistantAvailable(mAssistantAvailable, mLongPressHomeEnabled);
+ mStateListeners.add(listener);
+ if (!mTogglingNavbarTaskbar && mStateListeners.size() == 1) {
+ setupOnFirstBar();
+
+ // Update the state once the first bar is registered
+ updateAssistantAvailability();
+ updateA11yState();
+ mCommandQueue.recomputeDisableFlags(mContext.getDisplayId(), false /* animate */);
+ } else {
+ listener.updateAccessibilityServicesState();
+ listener.updateAssistantAvailable(mAssistantAvailable, mLongPressHomeEnabled);
+ }
+ listener.updateWallpaperVisibility(mWallpaperVisible, mDefaultDisplayId);
+ listener.updateRotationWatcherState(mRotationWatcherRotation);
}
+ /**
+ * Removes a previously registered listener.
+ */
public void removeNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) {
- mA11yEventListeners.remove(listener);
+ mStateListeners.remove(listener);
+ if (!mTogglingNavbarTaskbar && mStateListeners.isEmpty()) {
+ cleanupAfterLastBar();
+ }
}
private void dispatchA11yEventUpdate() {
- for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) {
+ for (NavbarTaskbarStateUpdater listener : mStateListeners) {
listener.updateAccessibilityServicesState();
}
}
private void dispatchAssistantEventUpdate(boolean assistantAvailable,
boolean longPressHomeEnabled) {
- for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) {
+ for (NavbarTaskbarStateUpdater listener : mStateListeners) {
listener.updateAssistantAvailable(assistantAvailable, longPressHomeEnabled);
}
}
@Override
public void onAccessibilityServicesStateChanged(AccessibilityManager manager) {
- dispatchA11yEventUpdate();
updateA11yState();
}
@Override
public void onAccessibilityButtonModeChanged(int mode) {
updateA11yState();
- dispatchA11yEventUpdate();
}
@Override
public void onAccessibilityButtonTargetsChanged(String targets) {
updateA11yState();
- dispatchA11yEventUpdate();
}
/**
@@ -262,6 +381,8 @@ public final class NavBarHelper implements
updateSystemAction(clickable, SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON);
updateSystemAction(longClickable, SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON_CHOOSER);
}
+
+ dispatchA11yEventUpdate();
}
/**
@@ -319,6 +440,10 @@ public final class NavBarHelper implements
return mLongPressHomeEnabled;
}
+ public EdgeBackGestureHandler getEdgeBackGestureHandler() {
+ return mEdgeBackGestureHandler;
+ }
+
@Override
public void startAssistant(Bundle bundle) {
mAssistManagerLazy.get().startAssist(bundle);
@@ -357,6 +482,18 @@ public final class NavBarHelper implements
mWindowState = state;
}
+ private void dispatchWallpaperVisibilityChanged(boolean visible, int displayId) {
+ for (NavbarTaskbarStateUpdater listener : mStateListeners) {
+ listener.updateWallpaperVisibility(visible, displayId);
+ }
+ }
+
+ private void dispatchRotationChanged(int rotation) {
+ for (NavbarTaskbarStateUpdater listener : mStateListeners) {
+ listener.updateRotationWatcherState(rotation);
+ }
+ }
+
public CurrentSysuiState getCurrentSysuiState() {
return new CurrentSysuiState();
}
@@ -368,6 +505,8 @@ public final class NavBarHelper implements
public interface NavbarTaskbarStateUpdater {
void updateAccessibilityServicesState();
void updateAssistantAvailable(boolean available, boolean longPressHomeEnabled);
+ default void updateWallpaperVisibility(boolean visible, int displayId) {}
+ default void updateRotationWatcherState(int rotation) {}
}
/** Data class to help Taskbar/Navbar initiate state correctly when switching between the two.*/
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 97c290d3e1f0..941770cff014 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -37,7 +37,7 @@ import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSE
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.HOME_BUTTON_LONG_PRESS_DURATION_MS;
import static com.android.systemui.navigationbar.NavBarHelper.transitionMode;
import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
-import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
+import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY;
@@ -164,7 +164,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Executor;
-import java.util.function.Consumer;
import javax.inject.Inject;
@@ -209,7 +208,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private final Optional<Recents> mRecentsOptional;
private final DeviceConfigProxy mDeviceConfigProxy;
private final NavigationBarTransitions mNavigationBarTransitions;
- private final EdgeBackGestureHandler mEdgeBackGestureHandler;
private final Optional<BackAnimation> mBackAnimation;
private final Handler mHandler;
private final UiEventLogger mUiEventLogger;
@@ -221,6 +219,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private final DisplayTracker mDisplayTracker;
private final RegionSamplingHelper mRegionSamplingHelper;
private final int mNavColorSampleMargin;
+ private EdgeBackGestureHandler mEdgeBackGestureHandler;
private NavigationBarFrame mFrame;
private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
@@ -350,6 +349,21 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mLongPressHomeEnabled = longPressHomeEnabled;
updateAssistantEntrypoints(available, longPressHomeEnabled);
}
+
+ @Override
+ public void updateWallpaperVisibility(boolean visible, int displayId) {
+ mNavigationBarTransitions.setWallpaperVisibility(visible);
+ }
+
+ @Override
+ public void updateRotationWatcherState(int rotation) {
+ if (mIsOnDefaultDisplay && mView != null) {
+ mView.getRotationButtonController().onRotationWatcherChanged(rotation);
+ if (mView.needsReorient(rotation)) {
+ repositionNavigationBar(rotation);
+ }
+ }
+ }
};
private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
@@ -543,7 +557,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
DeadZone deadZone,
DeviceConfigProxy deviceConfigProxy,
NavigationBarTransitions navigationBarTransitions,
- EdgeBackGestureHandler edgeBackGestureHandler,
Optional<BackAnimation> backAnimation,
UserContextProvider userContextProvider,
WakefulnessLifecycle wakefulnessLifecycle,
@@ -573,7 +586,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mDeadZone = deadZone;
mDeviceConfigProxy = deviceConfigProxy;
mNavigationBarTransitions = navigationBarTransitions;
- mEdgeBackGestureHandler = edgeBackGestureHandler;
mBackAnimation = backAnimation;
mHandler = mainHandler;
mUiEventLogger = uiEventLogger;
@@ -589,6 +601,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mWakefulnessLifecycle = wakefulnessLifecycle;
mTaskStackChangeListeners = taskStackChangeListeners;
mDisplayTracker = displayTracker;
+ mEdgeBackGestureHandler = navBarHelper.getEdgeBackGestureHandler();
mNavColorSampleMargin = getResources()
.getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
@@ -677,13 +690,14 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
// start firing, since the latter is source of truth
parseCurrentSysuiState();
mCommandQueue.addCallback(this);
- mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled();
- mNavBarHelper.init();
mHomeButtonLongPressDurationMs = Optional.of(mDeviceConfigProxy.getLong(
DeviceConfig.NAMESPACE_SYSTEMUI,
HOME_BUTTON_LONG_PRESS_DURATION_MS,
/* defaultValue = */ 0
)).filter(duration -> duration != 0);
+ // This currently MUST be called after mHomeButtonLongPressDurationMs is initialized since
+ // the registration callbacks will trigger code that uses it
+ mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
mDeviceConfigProxy.addOnPropertiesChangedListener(
DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post, mOnPropertiesChangedListener);
@@ -707,9 +721,9 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mCommandQueue.removeCallback(this);
mWindowManager.removeViewImmediate(mView.getRootView());
mNavigationModeController.removeListener(mModeChangedListener);
+ mEdgeBackGestureHandler.setStateChangeCallback(null);
mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
- mNavBarHelper.destroy();
mNotificationShadeDepthController.removeListener(mDepthListener);
mDeviceConfigProxy.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
@@ -746,8 +760,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mView.getViewRootImpl().addSurfaceChangedCallback(mSurfaceChangedCallback);
notifyNavigationBarSurface();
- mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
-
mPipOptional.ifPresent(mView::addPipExclusionBoundsChangeListener);
mBackAnimation.ifPresent(mView::registerBackAnimation);
@@ -765,7 +777,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
if (mIsOnDefaultDisplay) {
final RotationButtonController rotationButtonController =
mView.getRotationButtonController();
- rotationButtonController.setRotationCallback(mRotationWatcher);
// Reset user rotation pref to match that of the WindowManager if starting in locked
// mode. This will automatically happen when switching from auto-rotate to locked mode.
@@ -799,9 +810,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
@Override
public void onViewDetached() {
- final RotationButtonController rotationButtonController =
- mView.getRotationButtonController();
- rotationButtonController.setRotationCallback(null);
mView.setUpdateActiveTouchRegionsCallback(null);
getBarTransitions().destroy();
mOverviewProxyService.removeCallback(mOverviewProxyListener);
@@ -1487,6 +1495,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
}
void updateAccessibilityStateFlags() {
+ mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled();
if (mView != null) {
int a11yFlags = mNavBarHelper.getA11yButtonState();
boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
@@ -1702,12 +1711,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
return mNavBarMode == NAV_BAR_MODE_GESTURAL && mOrientationHandle != null;
}
- private final Consumer<Integer> mRotationWatcher = rotation -> {
- if (mView != null && mView.needsReorient(rotation)) {
- repositionNavigationBar(rotation);
- }
- };
-
private final UserTracker.Callback mUserChangedCallback =
new UserTracker.Callback() {
@Override
@@ -1724,7 +1727,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private void setNavigationIconHints(int hints) {
if (hints == mNavigationIconHints) return;
- if (!isTablet(mContext)) {
+ if (!isLargeScreen(mContext)) {
// All IME functions handled by launcher via Sysui flags for large screen
final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
final boolean oldBackAlt =
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 8c19111cab24..21398e23cc10 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -21,7 +21,7 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler.DEBUG_MISSING_GESTURE_TAG;
-import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
+import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -90,8 +90,9 @@ public class NavigationBarController implements
private final DisplayTracker mDisplayTracker;
private final DisplayManager mDisplayManager;
private final TaskbarDelegate mTaskbarDelegate;
+ private final NavBarHelper mNavBarHelper;
private int mNavMode;
- @VisibleForTesting boolean mIsTablet;
+ @VisibleForTesting boolean mIsLargeScreen;
/** A displayId - nav bar maps. */
@VisibleForTesting
@@ -133,21 +134,22 @@ public class NavigationBarController implements
configurationController.addCallback(this);
mConfigChanges.applyNewConfig(mContext.getResources());
mNavMode = navigationModeController.addListener(this);
+ mNavBarHelper = navBarHelper;
mTaskbarDelegate = taskbarDelegate;
mTaskbarDelegate.setDependencies(commandQueue, overviewProxyService,
navBarHelper, navigationModeController, sysUiFlagsContainer,
dumpManager, autoHideController, lightBarController, pipOptional,
backAnimation.orElse(null), taskStackChangeListeners);
- mIsTablet = isTablet(mContext);
+ mIsLargeScreen = isLargeScreen(mContext);
dumpManager.registerDumpable(this);
}
@Override
public void onConfigChanged(Configuration newConfig) {
- boolean isOldConfigTablet = mIsTablet;
- mIsTablet = isTablet(mContext);
+ boolean isOldConfigLargeScreen = mIsLargeScreen;
+ mIsLargeScreen = isLargeScreen(mContext);
boolean willApplyConfig = mConfigChanges.applyNewConfig(mContext.getResources());
- boolean largeScreenChanged = mIsTablet != isOldConfigTablet;
+ boolean largeScreenChanged = mIsLargeScreen != isOldConfigLargeScreen;
// TODO(b/243765256): Disable this logging once b/243765256 is fixed.
Log.i(DEBUG_MISSING_GESTURE_TAG, "NavbarController: newConfig=" + newConfig
+ " mTaskbarDelegate initialized=" + mTaskbarDelegate.isInitialized()
@@ -235,15 +237,21 @@ public class NavigationBarController implements
/** @return {@code true} if taskbar is enabled, false otherwise */
private boolean initializeTaskbarIfNecessary() {
- // Enable for tablet or (phone AND flag is set); assuming phone = !mIsTablet
- boolean taskbarEnabled = mIsTablet || mFeatureFlags.isEnabled(Flags.HIDE_NAVBAR_WINDOW);
+ // Enable for large screens or (phone AND flag is set); assuming phone = !mIsLargeScreen
+ boolean taskbarEnabled = mIsLargeScreen || mFeatureFlags.isEnabled(
+ Flags.HIDE_NAVBAR_WINDOW);
if (taskbarEnabled) {
Trace.beginSection("NavigationBarController#initializeTaskbarIfNecessary");
+ final int displayId = mContext.getDisplayId();
+ // Hint to NavBarHelper if we are replacing an existing bar to skip extra work
+ mNavBarHelper.setTogglingNavbarTaskbar(mNavigationBars.contains(displayId));
// Remove navigation bar when taskbar is showing
- removeNavigationBar(mContext.getDisplayId());
- mTaskbarDelegate.init(mContext.getDisplayId());
+ removeNavigationBar(displayId);
+ mTaskbarDelegate.init(displayId);
+ mNavBarHelper.setTogglingNavbarTaskbar(false);
Trace.endSection();
+
} else {
mTaskbarDelegate.destroy();
}
@@ -258,7 +266,7 @@ public class NavigationBarController implements
@Override
public void onDisplayReady(int displayId) {
Display display = mDisplayManager.getDisplay(displayId);
- mIsTablet = isTablet(mContext);
+ mIsLargeScreen = isLargeScreen(mContext);
createNavigationBar(display, null /* savedState */, null /* result */);
}
@@ -470,7 +478,7 @@ public class NavigationBarController implements
@Override
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
- pw.println("mIsTablet=" + mIsTablet);
+ pw.println("mIsLargeScreen=" + mIsLargeScreen);
pw.println("mNavMode=" + mNavMode);
for (int i = 0; i < mNavigationBars.size(); i++) {
if (i > 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
index a4de9ffbfa51..1d73bc205dc4 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
@@ -21,11 +21,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.systemui.util.Utils.isGesturalModeOnDefaultDisplay;
import android.graphics.Rect;
-import android.os.Handler;
-import android.os.RemoteException;
import android.util.SparseArray;
-import android.view.IWallpaperVisibilityListener;
-import android.view.IWindowManager;
import android.view.View;
import com.android.systemui.R;
@@ -62,8 +58,6 @@ public final class NavigationBarTransitions extends BarTransitions implements
}
private final NavigationBarView mView;
- @org.jetbrains.annotations.NotNull
- private final IWindowManager mWindowManagerService;
private final LightBarTransitionsController mLightTransitionsController;
private final DisplayTracker mDisplayTracker;
private final boolean mAllowAutoDimWallpaperNotVisible;
@@ -75,37 +69,20 @@ public final class NavigationBarTransitions extends BarTransitions implements
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
private List<DarkIntensityListener> mDarkIntensityListeners;
- private final Handler mHandler = Handler.getMain();
- private final IWallpaperVisibilityListener mWallpaperVisibilityListener =
- new IWallpaperVisibilityListener.Stub() {
- @Override
- public void onWallpaperVisibilityChanged(boolean newVisibility,
- int displayId) throws RemoteException {
- mWallpaperVisible = newVisibility;
- mHandler.post(() -> applyLightsOut(true, false));
- }
- };
-
@Inject
public NavigationBarTransitions(
NavigationBarView view,
- IWindowManager windowManagerService,
LightBarTransitionsController.Factory lightBarTransitionsControllerFactory,
DisplayTracker displayTracker) {
super(view, R.drawable.nav_background);
+
mView = view;
- mWindowManagerService = windowManagerService;
mLightTransitionsController = lightBarTransitionsControllerFactory.create(this);
mDisplayTracker = displayTracker;
mAllowAutoDimWallpaperNotVisible = view.getContext().getResources()
.getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper);
mDarkIntensityListeners = new ArrayList();
- try {
- mWallpaperVisible = mWindowManagerService.registerWallpaperVisibilityListener(
- mWallpaperVisibilityListener, mDisplayTracker.getDefaultDisplayId());
- } catch (RemoteException e) {
- }
mView.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
View currentView = mView.getCurrentView();
@@ -127,14 +104,14 @@ public final class NavigationBarTransitions extends BarTransitions implements
@Override
public void destroy() {
- try {
- mWindowManagerService.unregisterWallpaperVisibilityListener(mWallpaperVisibilityListener,
- mDisplayTracker.getDefaultDisplayId());
- } catch (RemoteException e) {
- }
mLightTransitionsController.destroy();
}
+ void setWallpaperVisibility(boolean visible) {
+ mWallpaperVisible = visible;
+ applyLightsOut(true, false);
+ }
+
@Override
public void setAutoDim(boolean autoDim) {
// Ensure we aren't in gestural nav if we are triggering auto dim
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 63fb4996fbbf..5d598e8dc765 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -1093,13 +1093,10 @@ public class NavigationBarView extends FrameLayout {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- // This needs to happen first as it can changed the enabled state which can affect whether
- // the back button is visible
- mEdgeBackGestureHandler.onNavBarAttached();
requestApplyInsets();
reorient();
if (mRotationButtonController != null) {
- mRotationButtonController.registerListeners();
+ mRotationButtonController.registerListeners(false /* registerRotationWatcher */);
}
updateNavButtonIcons();
@@ -1115,8 +1112,6 @@ public class NavigationBarView extends FrameLayout {
mFloatingRotationButton.hide();
mRotationButtonController.unregisterListeners();
}
-
- mEdgeBackGestureHandler.onNavBarDetached();
}
void dump(PrintWriter pw) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index 6ee86aa021a3..85d0ce53d9ff 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -41,7 +41,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode
import android.app.StatusBarManager;
import android.app.StatusBarManager.WindowVisibleState;
-import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -68,7 +67,6 @@ import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -78,6 +76,7 @@ import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.BarTransitions;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.pip.Pip;
@@ -94,7 +93,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
Dumpable {
private static final String TAG = TaskbarDelegate.class.getSimpleName();
- private final EdgeBackGestureHandler mEdgeBackGestureHandler;
+ private EdgeBackGestureHandler mEdgeBackGestureHandler;
private final LightBarTransitionsController.Factory mLightBarTransitionsControllerFactory;
private boolean mInitialized;
private CommandQueue mCommandQueue;
@@ -169,16 +168,20 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
private BackAnimation mBackAnimation;
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Inject
public TaskbarDelegate(Context context,
- EdgeBackGestureHandler.Factory edgeBackGestureHandlerFactory,
- LightBarTransitionsController.Factory lightBarTransitionsControllerFactory) {
+ LightBarTransitionsController.Factory lightBarTransitionsControllerFactory,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
mLightBarTransitionsControllerFactory = lightBarTransitionsControllerFactory;
- mEdgeBackGestureHandler = edgeBackGestureHandlerFactory.create(context);
mContext = context;
mDisplayManager = mContext.getSystemService(DisplayManager.class);
- mPipListener = mEdgeBackGestureHandler::setPipStashExclusionBounds;
+ mPipListener = (bounds) -> {
+ mEdgeBackGestureHandler.setPipStashExclusionBounds(bounds);
+ };
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ mStatusBarKeyguardViewManager.setTaskbarDelegate(this);
}
public void setDependencies(CommandQueue commandQueue,
@@ -204,6 +207,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
mBackAnimation = backAnimation;
mLightBarTransitionsController = createLightBarTransitionsController();
mTaskStackChangeListeners = taskStackChangeListeners;
+ mEdgeBackGestureHandler = navBarHelper.getEdgeBackGestureHandler();
}
// Separated into a method to keep setDependencies() clean/readable.
@@ -236,8 +240,6 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
mOverviewProxyService.addCallback(this);
onNavigationModeChanged(mNavigationModeController.addListener(this));
mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
- mNavBarHelper.init();
- mEdgeBackGestureHandler.onNavBarAttached();
// Initialize component callback
Display display = mDisplayManager.getDisplay(displayId);
mWindowContext = mContext.createWindowContext(display, TYPE_APPLICATION, null);
@@ -261,8 +263,6 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
mOverviewProxyService.removeCallback(this);
mNavigationModeController.removeListener(this);
mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
- mNavBarHelper.destroy();
- mEdgeBackGestureHandler.onNavBarDetached();
mScreenPinningNotify = null;
mWindowContext = null;
mAutoHideController.setNavigationBar(null);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
index f335733b430c..c76cfbdfe48c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
@@ -2,19 +2,15 @@ package com.android.systemui.navigationbar.gestural
import android.content.Context
import android.content.res.Configuration
-import android.content.res.TypedArray
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.graphics.RectF
import android.util.MathUtils.min
-import android.util.TypedValue
import android.view.View
-import androidx.appcompat.view.ContextThemeWrapper
import androidx.dynamicanimation.animation.FloatPropertyCompat
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
-import com.android.internal.R.style.Theme_DeviceDefault
import com.android.internal.util.LatencyTracker
import com.android.settingslib.Utils
import com.android.systemui.navigationbar.gestural.BackPanelController.DelayedOnAnimationEndListener
@@ -159,26 +155,21 @@ class BackPanel(
val isDeviceInNightTheme = resources.configuration.uiMode and
Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
- val colorControlActivated = ContextThemeWrapper(context, Theme_DeviceDefault)
- .run {
- val typedValue = TypedValue()
- val a: TypedArray = obtainStyledAttributes(typedValue.data,
- intArrayOf(android.R.attr.colorControlActivated))
- val color = a.getColor(0, 0)
- a.recycle()
- color
- }
-
- val colorPrimary =
- Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
-
- arrowPaint.color = Utils.getColorAccentDefaultColor(context)
+ arrowPaint.color = Utils.getColorAttrDefaultColor(context,
+ if (isDeviceInNightTheme) {
+ com.android.internal.R.attr.colorAccentPrimary
+ } else {
+ com.android.internal.R.attr.textColorPrimary
+ }
+ )
- arrowBackgroundPaint.color = if (isDeviceInNightTheme) {
- colorPrimary
- } else {
- colorControlActivated
- }
+ arrowBackgroundPaint.color = Utils.getColorAttrDefaultColor(context,
+ if (isDeviceInNightTheme) {
+ com.android.internal.R.attr.colorSurface
+ } else {
+ com.android.internal.R.attr.colorAccentSecondary
+ }
+ )
}
inner class AnimatedFloat(
@@ -414,9 +405,9 @@ class BackPanel(
) {
horizontalTranslation.updateRestingPosition(restingParams.horizontalTranslation)
scale.updateRestingPosition(restingParams.scale)
- arrowAlpha.updateRestingPosition(restingParams.arrowDimens.alpha)
backgroundAlpha.updateRestingPosition(restingParams.backgroundDimens.alpha)
+ arrowAlpha.updateRestingPosition(restingParams.arrowDimens.alpha, animate)
arrowLength.updateRestingPosition(restingParams.arrowDimens.length, animate)
arrowHeight.updateRestingPosition(restingParams.arrowDimens.height, animate)
scalePivotX.updateRestingPosition(restingParams.backgroundDimens.width, animate)
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
index 367d12547b9f..ce1c8daf1d45 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
@@ -55,12 +55,12 @@ private const val PX_PER_MS = 1
internal const val MIN_DURATION_ACTIVE_ANIMATION = 300L
private const val MIN_DURATION_CANCELLED_ANIMATION = 200L
-private const val MIN_DURATION_COMMITTED_ANIMATION = 200L
+private const val MIN_DURATION_COMMITTED_ANIMATION = 120L
private const val MIN_DURATION_INACTIVE_BEFORE_FLUNG_ANIMATION = 50L
private const val MIN_DURATION_CONSIDERED_AS_FLING = 100L
private const val FAILSAFE_DELAY_MS = 350L
-private const val POP_ON_FLING_DELAY = 160L
+private const val POP_ON_FLING_DELAY = 140L
internal val VIBRATE_ACTIVATED_EFFECT =
VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)
@@ -148,8 +148,6 @@ class BackPanelController internal constructor(
private var gestureSinceActionDown = 0L
private var gestureEntryTime = 0L
private var gestureActiveTime = 0L
- private var gestureInactiveOrEntryTime = 0L
- private var gestureArrowStrokeVisibleTime = 0L
private val elapsedTimeSinceActionDown
get() = SystemClock.uptimeMillis() - gestureSinceActionDown
@@ -441,34 +439,44 @@ class BackPanelController internal constructor(
updateArrowStateOnMove(yTranslation, xTranslation)
- when (currentState) {
- GestureState.ACTIVE -> {
- stretchActiveBackIndicator(fullScreenProgress(xTranslation))
- }
- GestureState.ENTRY -> {
- val progress = staticThresholdProgress(xTranslation)
- stretchEntryBackIndicator(progress)
-
- params.arrowStrokeAlphaSpring.get(progress).takeIf { it.isNewState }?.let {
- mView.popArrowAlpha(0f, it.value)
- }
- }
- GestureState.INACTIVE -> {
- val progress = reactivationThresholdProgress(totalTouchDelta)
- stretchInactiveBackIndicator(progress)
+ val gestureProgress = when (currentState) {
+ GestureState.ACTIVE -> fullScreenProgress(xTranslation)
+ GestureState.ENTRY -> staticThresholdProgress(xTranslation)
+ GestureState.INACTIVE -> reactivationThresholdProgress(totalTouchDelta)
+ else -> null
+ }
- params.arrowStrokeAlphaSpring.get(progress).takeIf { it.isNewState }?.let {
- gestureArrowStrokeVisibleTime = SystemClock.uptimeMillis()
- mView.popArrowAlpha(0f, it.value)
- }
+ gestureProgress?.let {
+ when (currentState) {
+ GestureState.ACTIVE -> stretchActiveBackIndicator(gestureProgress)
+ GestureState.ENTRY -> stretchEntryBackIndicator(gestureProgress)
+ GestureState.INACTIVE -> stretchInactiveBackIndicator(gestureProgress)
+ else -> {}
}
- else -> {}
}
- // set y translation
+ setArrowStrokeAlpha(gestureProgress)
setVerticalTranslation(yOffset)
}
+ private fun setArrowStrokeAlpha(gestureProgress: Float?) {
+ val strokeAlphaProgress = when (currentState) {
+ GestureState.ENTRY -> gestureProgress
+ GestureState.INACTIVE -> gestureProgress
+ GestureState.ACTIVE,
+ GestureState.FLUNG,
+ GestureState.COMMITTED -> 1f
+ GestureState.CANCELLED,
+ GestureState.GONE -> 0f
+ }
+
+ strokeAlphaProgress?.let { progress ->
+ params.arrowStrokeAlphaSpring.get(progress).takeIf { it.isNewState }?.let {
+ mView.popArrowAlpha(0f, it.value)
+ }
+ }
+ }
+
private fun setVerticalTranslation(yOffset: Float) {
val yTranslation = abs(yOffset)
val maxYOffset = (mView.height - params.entryIndicator.backgroundDimens.height) / 2f
@@ -599,7 +607,7 @@ class BackPanelController internal constructor(
private fun isFlungAwayFromEdge(endX: Float, startX: Float = touchDeltaStartX): Boolean {
val minDistanceConsideredForFling = ViewConfiguration.get(context).scaledTouchSlop
- val flingDistance = abs(endX - startX)
+ val flingDistance = if (mView.isLeftPanel) endX - startX else startX - endX
val isPastFlingVelocity = isDragAwayFromEdge(
velocityPxPerSecThreshold =
ViewConfiguration.get(context).scaledMinimumFlingVelocity)
@@ -764,7 +772,7 @@ class BackPanelController internal constructor(
GestureState.ENTRY,
GestureState.INACTIVE -> params.entryIndicator.arrowDimens
GestureState.ACTIVE -> params.activeIndicator.arrowDimens
- GestureState.FLUNG,
+ GestureState.FLUNG -> params.flungIndicator.arrowDimens
GestureState.COMMITTED -> params.committedIndicator.arrowDimens
GestureState.CANCELLED -> params.cancelledIndicator.arrowDimens
},
@@ -825,7 +833,6 @@ class BackPanelController internal constructor(
updateRestingArrowDimens()
gestureEntryTime = SystemClock.uptimeMillis()
- gestureInactiveOrEntryTime = SystemClock.uptimeMillis()
}
GestureState.ACTIVE -> {
previousXTranslationOnActiveOffset = previousXTranslation
@@ -857,7 +864,13 @@ class BackPanelController internal constructor(
}
GestureState.INACTIVE -> {
- gestureInactiveOrEntryTime = SystemClock.uptimeMillis()
+
+ // Typically entering INACTIVE means
+ // totalTouchDelta <= deactivationSwipeTriggerThreshold
+ // but because we can also independently enter this state
+ // if touch Y >> touch X, we force it to deactivationSwipeTriggerThreshold
+ // so that gesture progress in this state is consistent regardless of entry
+ totalTouchDelta = params.deactivationSwipeTriggerThreshold
val startingVelocity = convertVelocityToSpringStartingVelocity(
valueOnFastVelocity = -1.05f,
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 eea0e4cd94b9..c6f3968cec98 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -453,7 +453,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
}
/**
- * @see NavigationBarView#onAttachedToWindow()
+ * Called when the nav/task bar is attached.
*/
public void onNavBarAttached() {
mIsAttached = true;
@@ -465,7 +465,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
}
/**
- * @see NavigationBarView#onDetachedFromWindow()
+ * Called when the nav/task bar is detached.
*/
public void onNavBarDetached() {
mIsAttached = false;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
index 0c0002221244..d46333a50c8d 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
@@ -9,8 +9,8 @@ import com.android.systemui.R
data class EdgePanelParams(private var resources: Resources) {
data class ArrowDimens(
- val length: Float = 0f,
- val height: Float = 0f,
+ val length: Float? = 0f,
+ val height: Float? = 0f,
val alpha: Float = 0f,
var alphaSpring: SpringForce? = null,
val heightSpring: SpringForce? = null,
@@ -139,17 +139,17 @@ data class EdgePanelParams(private var resources: Resources) {
entryWidthInterpolator = PathInterpolator(.19f, 1.27f, .71f, .86f)
entryWidthTowardsEdgeInterpolator = PathInterpolator(1f, -3f, 1f, 1.2f)
- activeWidthInterpolator = PathInterpolator(.15f, .48f, .46f, .89f)
+ activeWidthInterpolator = PathInterpolator(.32f, 0f, .16f, .94f)
arrowAngleInterpolator = entryWidthInterpolator
translationInterpolator = PathInterpolator(0.2f, 1.0f, 1.0f, 1.0f)
farCornerInterpolator = PathInterpolator(.03f, .19f, .14f, 1.09f)
edgeCornerInterpolator = PathInterpolator(0f, 1.11f, .85f, .84f)
heightInterpolator = PathInterpolator(1f, .05f, .9f, -0.29f)
- val showArrowOnProgressValue = .2f
+ val showArrowOnProgressValue = .23f
val showArrowOnProgressValueFactor = 1.05f
- val entryActiveHorizontalTranslationSpring = createSpring(675f, 0.8f)
+ val entryActiveHorizontalTranslationSpring = createSpring(800f, 0.8f)
val activeCommittedArrowLengthSpring = createSpring(1500f, 0.29f)
val activeCommittedArrowHeightSpring = createSpring(1500f, 0.29f)
val flungCommittedEdgeCornerSpring = createSpring(10000f, 1f)
@@ -178,7 +178,7 @@ data class EdgePanelParams(private var resources: Resources) {
height = getDimen(R.dimen.navigation_edge_entry_background_height),
edgeCornerRadius = getDimen(R.dimen.navigation_edge_entry_edge_corners),
farCornerRadius = getDimen(R.dimen.navigation_edge_entry_far_corners),
- alphaSpring = createSpring(900f, 1f),
+ alphaSpring = createSpring(1100f, 1f),
widthSpring = createSpring(450f, 0.65f),
heightSpring = createSpring(1500f, 0.45f),
farCornerRadiusSpring = createSpring(300f, 0.5f),
@@ -232,7 +232,7 @@ data class EdgePanelParams(private var resources: Resources) {
getDimen(R.dimen.navigation_edge_pre_threshold_edge_corners),
farCornerRadius =
getDimen(R.dimen.navigation_edge_pre_threshold_far_corners),
- widthSpring = createSpring(200f, 0.65f),
+ widthSpring = createSpring(250f, 0.65f),
heightSpring = createSpring(1500f, 0.45f),
farCornerRadiusSpring = createSpring(200f, 1f),
edgeCornerRadiusSpring = createSpring(150f, 0.5f),
@@ -244,6 +244,8 @@ data class EdgePanelParams(private var resources: Resources) {
arrowDimens = activeIndicator.arrowDimens.copy(
lengthSpring = activeCommittedArrowLengthSpring,
heightSpring = activeCommittedArrowHeightSpring,
+ length = null,
+ height = null,
),
backgroundDimens = activeIndicator.backgroundDimens.copy(
alpha = 0f,
@@ -255,13 +257,15 @@ data class EdgePanelParams(private var resources: Resources) {
farCornerRadiusSpring = flungCommittedFarCornerSpring,
),
scale = 0.85f,
- scaleSpring = createSpring(650f, 1f),
+ scaleSpring = createSpring(1150f, 1f),
)
flungIndicator = committedIndicator.copy(
arrowDimens = committedIndicator.arrowDimens.copy(
lengthSpring = createSpring(850f, 0.46f),
heightSpring = createSpring(850f, 0.46f),
+ length = activeIndicator.arrowDimens.length,
+ height = activeIndicator.arrowDimens.height
),
backgroundDimens = committedIndicator.backgroundDimens.copy(
widthSpring = flungCommittedWidthSpring,
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
index 6ab0da6fe3b3..75a0c6836c45 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
@@ -33,8 +33,8 @@ import javax.inject.Inject
* launched, creating a new shortcut for [CreateNoteTaskShortcutActivity], and will finish.
*
* @see <a
- * href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
- * a custom shortcut activity</a>
+ * href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
+ * a custom shortcut activity</a>
*/
internal class CreateNoteTaskShortcutActivity @Inject constructor() : ComponentActivity() {
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index 8ad2f867a073..79167f276576 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -16,7 +16,11 @@ package com.android.systemui.privacy
import android.content.Context
import android.util.AttributeSet
+import android.view.Gravity.CENTER_VERTICAL
+import android.view.Gravity.END
import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.ImageView
import android.widget.LinearLayout
import com.android.settingslib.Utils
@@ -35,7 +39,7 @@ class OngoingPrivacyChip @JvmOverloads constructor(
private var iconSize = 0
private var iconColor = 0
- private lateinit var iconsContainer: LinearLayout
+ private val iconsContainer: LinearLayout
var privacyList = emptyList<PrivacyItem>()
set(value) {
@@ -43,11 +47,13 @@ class OngoingPrivacyChip @JvmOverloads constructor(
updateView(PrivacyChipBuilder(context, field))
}
- override fun onFinishInflate() {
- super.onFinishInflate()
-
+ init {
+ inflate(context, R.layout.ongoing_privacy_chip, this)
+ id = R.id.privacy_chip
+ layoutParams = LayoutParams(WRAP_CONTENT, MATCH_PARENT, CENTER_VERTICAL or END)
+ clipChildren = true
+ clipToPadding = true
iconsContainer = requireViewById(R.id.icons_container)
-
updateResources()
}
@@ -107,6 +113,6 @@ class OngoingPrivacyChip @JvmOverloads constructor(
val padding = context.resources
.getDimensionPixelSize(R.dimen.ongoing_appops_chip_side_padding)
iconsContainer.setPaddingRelative(padding, 0, padding, 0)
- iconsContainer.background = context.getDrawable(R.drawable.privacy_chip_bg)
+ iconsContainer.background = context.getDrawable(R.drawable.statusbar_privacy_chip_bg)
}
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java b/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java
index 245cf89a8337..27510720ae2f 100644
--- a/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java
@@ -26,7 +26,10 @@ public class ProcessWrapper {
@Inject
public ProcessWrapper() {}
- public int getUserHandleIdentifier() {
- return android.os.Process.myUserHandle().getIdentifier();
+ /**
+ * Returns {@code true} if System User is running the current process.
+ */
+ public boolean isSystemUser() {
+ return android.os.Process.myUserHandle().isSystem();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/process/condition/UserProcessCondition.java b/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
index 5a21ea075ea3..80fbf9115065 100644
--- a/packages/SystemUI/src/com/android/systemui/process/condition/UserProcessCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
@@ -17,29 +17,26 @@
package com.android.systemui.process.condition;
import com.android.systemui.process.ProcessWrapper;
-import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.condition.Condition;
import javax.inject.Inject;
/**
- * {@link UserProcessCondition} provides a signal when the process handle belongs to the current
- * user.
+ * {@link SystemProcessCondition} checks to make sure the current process is being ran by the
+ * System User.
*/
-public class UserProcessCondition extends Condition {
+public class SystemProcessCondition extends Condition {
private final ProcessWrapper mProcessWrapper;
- private final UserTracker mUserTracker;
@Inject
- public UserProcessCondition(ProcessWrapper processWrapper, UserTracker userTracker) {
+ public SystemProcessCondition(ProcessWrapper processWrapper) {
+ super();
mProcessWrapper = processWrapper;
- mUserTracker = userTracker;
}
@Override
protected void start() {
- updateCondition(mUserTracker.getUserId()
- == mProcessWrapper.getUserHandleIdentifier());
+ updateCondition(mProcessWrapper.isSystemUser());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
index 62c99da5ed81..fb09c55dc544 100644
--- a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
@@ -26,8 +26,7 @@ import dagger.multibindings.StringKey
@Module
interface QRCodeScannerModule {
- /**
- */
+ /** */
@Binds
@IntoMap
@StringKey(QRCodeScannerTile.TILE_SPEC)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
index be93550158c6..c70cce9fec26 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
@@ -183,7 +183,7 @@ class AutoAddTracker @VisibleForTesting constructor(
}
fun getRestoredTilePosition(tile: String): Int =
- restoredTiles?.get(tile)?.index ?: QSTileHost.POSITION_AT_END
+ restoredTiles?.get(tile)?.index ?: QSHost.POSITION_AT_END
/**
* Returns `true` if the tile has been auto-added before
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index e1289a61d45d..a7aac5a4824d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -135,7 +135,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener
private int mNumQuickTiles;
private int mLastQQSTileHeight;
private float mLastPosition;
- private final QSTileHost mHost;
+ private final QSHost mHost;
private final Executor mExecutor;
private boolean mShowCollapsedOnKeyguard;
private int mQQSTop;
@@ -146,7 +146,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener
@Inject
public QSAnimator(QS qs, QuickQSPanel quickPanel, QuickStatusBarHeader quickStatusBarHeader,
QSPanelController qsPanelController,
- QuickQSPanelController quickQSPanelController, QSTileHost qsTileHost,
+ QuickQSPanelController quickQSPanelController, QSHost qsTileHost,
@Main Executor executor, TunerService tunerService,
QSExpansionPathInterpolator qsExpansionPathInterpolator) {
mQs = qs;
@@ -330,12 +330,8 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener
// Offset the translation animation on the views
// (that goes from 0 to getOffsetTranslation)
- int offsetWithQSBHTranslation =
- yOffset - mQuickStatusBarHeader.getOffsetTranslation();
- qqsTranslationYBuilder.addFloat(quickTileView, "translationY", 0,
- offsetWithQSBHTranslation);
- translationYBuilder.addFloat(tileView, "translationY",
- -offsetWithQSBHTranslation, 0);
+ qqsTranslationYBuilder.addFloat(quickTileView, "translationY", 0, yOffset);
+ translationYBuilder.addFloat(tileView, "translationY", -yOffset, 0);
translationXBuilder.addFloat(quickTileView, "translationX", 0, xOffset);
translationXBuilder.addFloat(tileView, "translationX", -xOffset, 0);
@@ -489,7 +485,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener
if (specs.isEmpty()) {
// specs should not be empty in a valid secondary page, as we scrolled to it.
// We may crash later on because there's a null animator.
- specs = mQsPanelController.getHost().mTileSpecs;
+ specs = mHost.getSpecs();
Log.e(TAG, "Trying to create animators for empty page " + page + ". Tiles: " + specs);
// return null;
}
@@ -614,7 +610,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener
View commonView = mQs.getView();
getRelativePositionInt(qsPosition, view1, commonView);
getRelativePositionInt(qqsPosition, view2, commonView);
- return (qsPosition[1] - qqsPosition[1]) - mQuickStatusBarHeader.getOffsetTranslation();
+ return qsPosition[1] - qqsPosition[1];
}
private boolean isIconInAnimatedRow(int count) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 0c242d9da25f..b7f9f6bc0e4a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -53,7 +53,6 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
private boolean mQsDisabled;
private int mContentHorizontalPadding = -1;
private boolean mClippingEnabled;
- private boolean mUseCombinedHeaders;
public QSContainerImpl(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -68,10 +67,6 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
}
- void setUseCombinedHeaders(boolean useCombinedHeaders) {
- mUseCombinedHeaders = useCombinedHeaders;
- }
-
@Override
public boolean hasOverlappingRendering() {
return false;
@@ -150,8 +145,7 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
void updateResources(QSPanelController qsPanelController,
QuickStatusBarHeaderController quickStatusBarHeaderController) {
int topPadding = QSUtils.getQsHeaderSystemIconsAreaHeight(mContext);
- if (mUseCombinedHeaders
- && !LargeScreenUtils.shouldUseLargeScreenShadeHeader(mContext.getResources())) {
+ if (!LargeScreenUtils.shouldUseLargeScreenShadeHeader(mContext.getResources())) {
topPadding = mContext.getResources()
.getDimensionPixelSize(R.dimen.large_screen_shade_header_height);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
index 28b4c8228d38..73a5faabda3b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
@@ -22,8 +22,6 @@ import android.content.res.Configuration;
import android.view.MotionEvent;
import android.view.View;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -66,15 +64,13 @@ public class QSContainerImplController extends ViewController<QSContainerImpl> {
QSPanelController qsPanelController,
QuickStatusBarHeaderController quickStatusBarHeaderController,
ConfigurationController configurationController,
- FalsingManager falsingManager,
- FeatureFlags featureFlags) {
+ FalsingManager falsingManager) {
super(view);
mQsPanelController = qsPanelController;
mQuickStatusBarHeaderController = quickStatusBarHeaderController;
mConfigurationController = configurationController;
mFalsingManager = falsingManager;
mQSPanelContainer = mView.getQSPanelContainer();
- view.setUseCombinedHeaders(featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 8ad102ece9b3..938a9c35c205 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -52,8 +52,8 @@ import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.compose.ComposeFacade;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.media.controls.ui.MediaHost;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.qs.QSContainerController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -61,6 +61,8 @@ import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder;
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -88,14 +90,11 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private final Rect mQsBounds = new Rect();
private final SysuiStatusBarStateController mStatusBarStateController;
- private final FalsingManager mFalsingManager;
private final KeyguardBypassController mBypassController;
private boolean mQsExpanded;
private boolean mHeaderAnimating;
private boolean mStackScrollerOverscrolling;
- private long mDelay;
-
private QSAnimator mQSAnimator;
private HeightListener mPanelView;
private QSSquishinessController mQSSquishinessController;
@@ -116,8 +115,9 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private final MediaHost mQqsMediaHost;
private final QSFragmentComponent.Factory mQsComponentFactory;
private final QSFragmentDisableFlagsLogger mQsFragmentDisableFlagsLogger;
- private final QSTileHost mHost;
+ private final LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
private final FeatureFlags mFeatureFlags;
+ private final QSLogger mLogger;
private final FooterActionsController mFooterActionsController;
private final FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
private final ListeningAndVisibilityLifecycleOwner mListeningAndVisibilityLifecycleOwner;
@@ -150,11 +150,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
*/
private boolean mTransitioningToFullShade;
- /**
- * Whether the next Quick settings
- */
- private boolean mAnimateNextQsUpdate;
-
private final DumpManager mDumpManager;
/**
@@ -169,37 +164,33 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
// visible;
private boolean mQsVisible;
- /**
- * Whether the notification panel uses the full width of the screen.
- *
- * Usually {@code true} on small screens, and {@code false} on large screens.
- */
- private boolean mIsNotificationPanelFullWidth;
+ private boolean mIsSmallScreen;
@Inject
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
- QSTileHost qsTileHost,
SysuiStatusBarStateController statusBarStateController, CommandQueue commandQueue,
@Named(QS_PANEL) MediaHost qsMediaHost,
@Named(QUICK_QS_PANEL) MediaHost qqsMediaHost,
KeyguardBypassController keyguardBypassController,
QSFragmentComponent.Factory qsComponentFactory,
QSFragmentDisableFlagsLogger qsFragmentDisableFlagsLogger,
- FalsingManager falsingManager, DumpManager dumpManager, FeatureFlags featureFlags,
+ DumpManager dumpManager, QSLogger qsLogger,
FooterActionsController footerActionsController,
- FooterActionsViewModel.Factory footerActionsViewModelFactory) {
+ FooterActionsViewModel.Factory footerActionsViewModelFactory,
+ LargeScreenShadeInterpolator largeScreenShadeInterpolator,
+ FeatureFlags featureFlags) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
mQsMediaHost = qsMediaHost;
mQqsMediaHost = qqsMediaHost;
mQsComponentFactory = qsComponentFactory;
mQsFragmentDisableFlagsLogger = qsFragmentDisableFlagsLogger;
+ mLogger = qsLogger;
+ mLargeScreenShadeInterpolator = largeScreenShadeInterpolator;
+ mFeatureFlags = featureFlags;
commandQueue.observe(getLifecycle(), this);
- mHost = qsTileHost;
- mFalsingManager = falsingManager;
mBypassController = keyguardBypassController;
mStatusBarStateController = statusBarStateController;
mDumpManager = dumpManager;
- mFeatureFlags = featureFlags;
mFooterActionsController = footerActionsController;
mFooterActionsViewModelFactory = footerActionsViewModelFactory;
mListeningAndVisibilityLifecycleOwner = new ListeningAndVisibilityLifecycleOwner();
@@ -241,7 +232,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
(v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
// Lazily update animators whenever the scrolling changes
mQSAnimator.requestAnimatorUpdate();
- mHeader.setExpandedScrollAmount(scrollY);
if (mScrollListener != null) {
mScrollListener.onQsPanelScrollChanged(scrollY);
}
@@ -621,7 +611,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
@Override
public void setIsNotificationPanelFullWidth(boolean isFullWidth) {
- mIsNotificationPanelFullWidth = isFullWidth;
+ mIsSmallScreen = isFullWidth;
}
@Override
@@ -661,8 +651,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
int heightDiff = getHeightDiff();
float panelTranslationY = translationScaleY * heightDiff;
- // Let the views animate their contents correctly by giving them the necessary context.
- mHeader.setExpansion(onKeyguardAndExpanded, expansion, panelTranslationY);
if (expansion < 1 && expansion > 0.99) {
if (mQuickQSPanelController.switchTileLayout(false)) {
mHeader.updateResources();
@@ -716,15 +704,17 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private void setAlphaAnimationProgress(float progress) {
final View view = getView();
if (progress == 0 && view.getVisibility() != View.INVISIBLE) {
+ mLogger.logVisibility("QS fragment", View.INVISIBLE);
view.setVisibility(View.INVISIBLE);
} else if (progress > 0 && view.getVisibility() != View.VISIBLE) {
+ mLogger.logVisibility("QS fragment", View.VISIBLE);
view.setVisibility((View.VISIBLE));
}
view.setAlpha(interpolateAlphaAnimationProgress(progress));
}
private float calculateAlphaProgress(float panelExpansionFraction) {
- if (mIsNotificationPanelFullWidth) {
+ if (mIsSmallScreen) {
// Small screens. QS alpha is not animated.
return 1;
}
@@ -759,7 +749,12 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
// Alpha progress should be linear on lockscreen shade expansion.
return progress;
}
- return ShadeInterpolation.getContentAlpha(progress);
+ if (mIsSmallScreen || !mFeatureFlags.isEnabled(
+ Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+ return ShadeInterpolation.getContentAlpha(progress);
+ } else {
+ return mLargeScreenShadeInterpolator.getQsAlpha(progress);
+ }
}
@VisibleForTesting
@@ -914,7 +909,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
getView().getViewTreeObserver().removeOnPreDrawListener(this);
getView().animate()
.translationY(0f)
- .setStartDelay(mDelay)
.setDuration(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.setListener(mAnimateHeaderSlidingInListener)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
index 1da30ade951b..a71e6ddb6abd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -14,15 +14,48 @@
package com.android.systemui.qs;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.res.Resources;
+import android.os.Build;
+import android.provider.Settings;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.util.leak.GarbageMonitor;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
public interface QSHost {
+ String TILES_SETTING = Settings.Secure.QS_TILES;
+ int POSITION_AT_END = -1;
+
+ /**
+ * Returns the default QS tiles for the context.
+ * @param context the context to obtain the resources from
+ * @return a list of specs of the default tiles
+ */
+ static List<String> getDefaultSpecs(Context context) {
+ final ArrayList<String> tiles = new ArrayList();
+
+ final Resources res = context.getResources();
+ final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
+
+ tiles.addAll(Arrays.asList(defaultTileList.split(",")));
+ if (Build.IS_DEBUGGABLE
+ && GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
+ tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
+ }
+ return tiles;
+ }
+
void warn(String message, Throwable t);
void collapsePanels();
void forceCollapsePanels();
@@ -37,6 +70,44 @@ public interface QSHost {
void removeTile(String tileSpec);
void removeTiles(Collection<String> specs);
+ List<String> getSpecs();
+ /**
+ * Create a view for a tile, iterating over all possible {@link QSFactory}.
+ *
+ * @see QSFactory#createTileView
+ */
+ QSTileView createTileView(Context themedContext, QSTile tile, boolean collapsedView);
+ /** Create a {@link QSTile} of a {@code tileSpec} type. */
+ QSTile createTile(String tileSpec);
+
+ /**
+ * Add a tile to the end
+ *
+ * @param spec string matching a pre-defined tilespec
+ */
+ void addTile(String spec);
+
+ /**
+ * Add a tile into the requested spot, or at the end if the position is greater than the number
+ * of tiles.
+ * @param spec string matching a pre-defined tilespec
+ * @param requestPosition -1 for end, 0 for beginning, or X for insertion at position X
+ */
+ void addTile(String spec, int requestPosition);
+ void addTile(ComponentName tile);
+
+ /**
+ * Adds a custom tile to the set of current tiles.
+ * @param tile the component name of the {@link android.service.quicksettings.TileService}
+ * @param end if true, the tile will be added at the end. If false, at the beginning.
+ */
+ void addTile(ComponentName tile, boolean end);
+ void removeTileByUser(ComponentName tile);
+ void changeTilesByUser(List<String> previousTiles, List<String> newTiles);
+
+ boolean isTileAdded(ComponentName componentName, int userId);
+ void setTileAdded(ComponentName componentName, int userId, boolean added);
+
int indexOf(String tileSpec);
InstanceId getNewInstanceId();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index a0be151e15a1..b476521f1975 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -79,7 +79,6 @@ public class QSPanel extends LinearLayout implements Tunable {
protected boolean mExpanded;
protected boolean mListening;
- @Nullable protected QSTileHost mHost;
private final List<OnConfigurationChangedListener> mOnConfigurationChangedListeners =
new ArrayList<>();
@@ -104,7 +103,6 @@ public class QSPanel extends LinearLayout implements Tunable {
private final Rect mClippingRect = new Rect();
private ViewGroup mMediaHostView;
private boolean mShouldMoveMediaOnExpansion = true;
- private boolean mUsingCombinedHeaders = false;
private QSLogger mQsLogger;
/**
* Specifies if we can collapse to QQS in current state. In split shade that should be always
@@ -155,10 +153,6 @@ public class QSPanel extends LinearLayout implements Tunable {
}
}
- void setUsingCombinedHeaders(boolean usingCombinedHeaders) {
- mUsingCombinedHeaders = usingCombinedHeaders;
- }
-
protected void setHorizontalContentContainerClipping() {
mHorizontalContentContainer.setClipChildren(true);
mHorizontalContentContainer.setClipToPadding(false);
@@ -364,11 +358,6 @@ public class QSPanel extends LinearLayout implements Tunable {
}
}
- @Nullable
- public QSTileHost getHost() {
- return mHost;
- }
-
public void updateResources() {
updatePadding();
@@ -383,9 +372,7 @@ public class QSPanel extends LinearLayout implements Tunable {
protected void updatePadding() {
final Resources res = mContext.getResources();
- int paddingTop = res.getDimensionPixelSize(
- mUsingCombinedHeaders ? R.dimen.qs_panel_padding_top_combined_headers
- : R.dimen.qs_panel_padding_top);
+ int paddingTop = res.getDimensionPixelSize(R.dimen.qs_panel_padding_top);
int paddingBottom = res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom);
setPaddingRelative(getPaddingStart(),
paddingTop,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 01dbb1825208..83b373d5e626 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -17,7 +17,6 @@
package com.android.systemui.qs;
import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE;
-import static com.android.systemui.flags.Flags.COMBINED_QS_HEADERS;
import static com.android.systemui.media.dagger.MediaModule.QS_PANEL;
import static com.android.systemui.qs.QSPanel.QS_SHOW_BRIGHTNESS;
import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER;
@@ -28,7 +27,6 @@ import android.view.View;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.controls.ui.MediaHierarchyManager;
import com.android.systemui.media.controls.ui.MediaHost;
import com.android.systemui.media.controls.ui.MediaHostState;
@@ -73,7 +71,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
@Inject
QSPanelController(QSPanel view, TunerService tunerService,
- QSTileHost qstileHost, QSCustomizerController qsCustomizerController,
+ QSHost qsHost, QSCustomizerController qsCustomizerController,
@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
@Named(QS_PANEL) MediaHost mediaHost,
QSTileRevealController.Factory qsTileRevealControllerFactory,
@@ -81,9 +79,8 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
BrightnessSliderController.Factory brightnessSliderFactory,
FalsingManager falsingManager,
- StatusBarKeyguardViewManager statusBarKeyguardViewManager,
- FeatureFlags featureFlags) {
- super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+ super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost,
metricsLogger, uiEventLogger, qsLogger, dumpManager);
mTunerService = tunerService;
mQsCustomizerController = qsCustomizerController;
@@ -96,7 +93,6 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mBrightnessController = brightnessControllerFactory.create(mBrightnessSliderController);
mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
- mView.setUsingCombinedHeaders(featureFlags.isEnabled(COMBINED_QS_HEADERS));
}
@Override
@@ -176,12 +172,6 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mBrightnessMirrorHandler.setController(brightnessMirrorController);
}
- /** Get the QSTileHost this panel uses. */
- public QSTileHost getHost() {
- return mHost;
- }
-
-
/** Update appearance of QSPanel. */
public void updateResources() {
mView.updateResources();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index bbdf6cc70541..2668d2e36731 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -64,7 +64,7 @@ import kotlin.jvm.functions.Function1;
public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewController<T>
implements Dumpable{
private static final String TAG = "QSPanelControllerBase";
- protected final QSTileHost mHost;
+ protected final QSHost mHost;
private final QSCustomizerController mQsCustomizerController;
private final boolean mUsingMediaPlayer;
protected final MediaHost mMediaHost;
@@ -128,7 +128,7 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
protected QSPanelControllerBase(
T view,
- QSTileHost host,
+ QSHost host,
QSCustomizerController qsCustomizerController,
@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
MediaHost mediaHost,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 98af9dfe7f37..0ead97976ad9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -18,7 +18,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
-import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings.Secure;
@@ -56,17 +55,14 @@ import com.android.systemui.settings.UserFileManager;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
-import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.util.settings.SecureSettings;
import org.jetbrains.annotations.NotNull;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
@@ -94,16 +90,13 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final int MAX_QS_INSTANCE_ID = 1 << 20;
- public static final int POSITION_AT_END = -1;
- public static final String TILES_SETTING = Secure.QS_TILES;
-
// Shared prefs that hold tile lifecycle info.
@VisibleForTesting
static final String TILES = "tiles_prefs";
private final Context mContext;
private final LinkedHashMap<String, QSTile> mTiles = new LinkedHashMap<>();
- protected final ArrayList<String> mTileSpecs = new ArrayList<>();
+ private final ArrayList<String> mTileSpecs = new ArrayList<>();
private final TunerService mTunerService;
private final PluginManager mPluginManager;
private final DumpManager mDumpManager;
@@ -117,7 +110,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
private final List<Callback> mCallbacks = new ArrayList<>();
@Nullable
private AutoTileManager mAutoTiles;
- private final StatusBarIconController mIconController;
private final ArrayList<QSFactory> mQsFactories = new ArrayList<>();
private int mCurrentUser;
private final Optional<CentralSurfaces> mCentralSurfacesOptional;
@@ -135,7 +127,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
@Inject
public QSTileHost(Context context,
- StatusBarIconController iconController,
QSFactory defaultFactory,
@Main Executor mainExecutor,
PluginManager pluginManager,
@@ -152,7 +143,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
TileLifecycleManager.Factory tileLifecycleManagerFactory,
UserFileManager userFileManager
) {
- mIconController = iconController;
mContext = context;
mUserContext = context;
mTunerService = tunerService;
@@ -186,10 +176,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
});
}
- public StatusBarIconController getIconController() {
- return mIconController;
- }
-
@Override
public InstanceId getNewInstanceId() {
return mInstanceIdSequence.newInstanceId();
@@ -438,12 +424,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
addTile(spec, POSITION_AT_END);
}
- /**
- * Add a tile into the requested spot, or at the end if the position is greater than the number
- * of tiles.
- * @param spec string matching a pre-defined tilespec
- * @param requestPosition -1 for end, 0 for beginning, or X for insertion at position X
- */
+ @Override
public void addTile(String spec, int requestPosition) {
mMainExecutor.execute(() ->
changeTileSpecs(tileSpecs -> {
@@ -483,15 +464,12 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
}
}
+ @Override
public void addTile(ComponentName tile) {
addTile(tile, /* end */ false);
}
- /**
- * Adds a custom tile to the set of current tiles.
- * @param tile the component name of the {@link android.service.quicksettings.TileService}
- * @param end if true, the tile will be added at the end. If false, at the beginning.
- */
+ @Override
public void addTile(ComponentName tile, boolean end) {
String spec = CustomTile.toSpec(tile);
addTile(spec, end ? POSITION_AT_END : 0);
@@ -501,6 +479,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
* This will call through {@link #changeTilesByUser}. It should only be used when a tile is
* removed by a <b>user action</b> like {@code adb}.
*/
+ @Override
public void removeTileByUser(ComponentName tile) {
mMainExecutor.execute(() -> {
List<String> newSpecs = new ArrayList<>(mTileSpecs);
@@ -519,6 +498,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
* that are removed.
*/
@MainThread
+ @Override
public void changeTilesByUser(List<String> previousTiles, List<String> newTiles) {
final List<String> copy = new ArrayList<>(previousTiles);
final int NP = copy.size();
@@ -542,8 +522,8 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
saveTilesToSettings(newTiles);
}
- /** Create a {@link QSTile} of a {@code tileSpec} type. */
@Nullable
+ @Override
public QSTile createTile(String tileSpec) {
for (int i = 0; i < mQsFactories.size(); i++) {
QSTile t = mQsFactories.get(i).createTile(tileSpec);
@@ -554,11 +534,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
return null;
}
- /**
- * Create a view for a tile, iterating over all possible {@link QSFactory}.
- *
- * @see QSFactory#createTileView
- */
+ @Override
public QSTileView createTileView(Context themedContext, QSTile tile, boolean collapsedView) {
for (int i = 0; i < mQsFactories.size(); i++) {
QSTileView view = mQsFactories.get(i)
@@ -578,6 +554,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
* tile.
* @param userId the user to check
*/
+ @Override
public boolean isTileAdded(ComponentName componentName, int userId) {
return mUserFileManager
.getSharedPreferences(TILES, 0, userId)
@@ -593,6 +570,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
* @param userId the user for this tile
* @param added {@code true} if the tile is being added, {@code false} otherwise
*/
+ @Override
public void setTileAdded(ComponentName componentName, int userId, boolean added) {
mUserFileManager.getSharedPreferences(TILES, 0, userId)
.edit()
@@ -600,6 +578,11 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
.apply();
}
+ @Override
+ public List<String> getSpecs() {
+ return mTileSpecs;
+ }
+
protected static List<String> loadTileSpecs(Context context, String tileList) {
final Resources res = context.getResources();
@@ -617,7 +600,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
if (tile.isEmpty()) continue;
if (tile.equals("default")) {
if (!addedDefault) {
- List<String> defaultSpecs = getDefaultSpecs(context);
+ List<String> defaultSpecs = QSHost.getDefaultSpecs(context);
for (String spec : defaultSpecs) {
if (!addedSpecs.contains(spec)) {
tiles.add(spec);
@@ -650,25 +633,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
return tiles;
}
- /**
- * Returns the default QS tiles for the context.
- * @param context the context to obtain the resources from
- * @return a list of specs of the default tiles
- */
- public static List<String> getDefaultSpecs(Context context) {
- final ArrayList<String> tiles = new ArrayList<String>();
-
- final Resources res = context.getResources();
- final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
-
- tiles.addAll(Arrays.asList(defaultTileList.split(",")));
- if (Build.IS_DEBUGGABLE
- && GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
- tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
- }
- return tiles;
- }
-
@Override
public void dump(PrintWriter pw, String[] args) {
pw.println("QSTileHost:");
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index 6aabe3b1ced1..2d543139a1b4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -48,7 +48,7 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
private final Provider<Boolean> mUsingCollapsedLandscapeMediaProvider;
@Inject
- QuickQSPanelController(QuickQSPanel view, QSTileHost qsTileHost,
+ QuickQSPanelController(QuickQSPanel view, QSHost qsHost,
QSCustomizerController qsCustomizerController,
@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
@Named(QUICK_QS_PANEL) MediaHost mediaHost,
@@ -57,7 +57,7 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
DumpManager dumpManager
) {
- super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
+ super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
uiEventLogger, qsLogger, dumpManager);
mUsingCollapsedLandscapeMediaProvider = usingCollapsedLandscapeMediaProvider;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index e696d131267f..691a1a14444a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -20,35 +20,15 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.Color;
-import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.Pair;
-import android.view.DisplayCutout;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.WindowInsets;
import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.Space;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.policy.SystemBarUtils;
-import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.battery.BatteryMeterView;
-import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
-import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
-import com.android.systemui.statusbar.phone.StatusIconContainer;
-import com.android.systemui.statusbar.policy.Clock;
-import com.android.systemui.statusbar.policy.VariableDateView;
import com.android.systemui.util.LargeScreenUtils;
-import java.util.List;
-
/**
* View that contains the top-most bits of the QS panel (primarily the status bar with date, time,
* battery, carrier info and privacy icons) and also contains the {@link QuickQSPanel}.
@@ -58,182 +38,30 @@ public class QuickStatusBarHeader extends FrameLayout {
private boolean mExpanded;
private boolean mQsDisabled;
- @Nullable
- private TouchAnimator mAlphaAnimator;
- @Nullable
- private TouchAnimator mTranslationAnimator;
- @Nullable
- private TouchAnimator mIconsAlphaAnimator;
- private TouchAnimator mIconsAlphaAnimatorFixed;
-
protected QuickQSPanel mHeaderQsPanel;
- private View mDatePrivacyView;
- private View mDateView;
- // DateView next to clock. Visible on QQS
- private VariableDateView mClockDateView;
- private View mStatusIconsView;
- private View mContainer;
-
- private View mQSCarriers;
- private ViewGroup mClockContainer;
- private Clock mClockView;
- private Space mDatePrivacySeparator;
- private View mClockIconsSeparator;
- private boolean mShowClockIconsSeparator;
- private View mRightLayout;
- private View mDateContainer;
- private View mPrivacyContainer;
-
- private BatteryMeterView mBatteryRemainingIcon;
- private StatusIconContainer mIconContainer;
- private View mPrivacyChip;
-
- @Nullable
- private TintedIconManager mTintedIconManager;
- @Nullable
- private QSExpansionPathInterpolator mQSExpansionPathInterpolator;
- private StatusBarContentInsetsProvider mInsetsProvider;
-
- private int mRoundedCornerPadding = 0;
- private int mWaterfallTopInset;
- private int mCutOutPaddingLeft;
- private int mCutOutPaddingRight;
- private float mKeyguardExpansionFraction;
- private int mTextColorPrimary = Color.TRANSPARENT;
- private int mTopViewMeasureHeight;
-
- @NonNull
- private List<String> mRssiIgnoredSlots = List.of();
- private boolean mIsSingleCarrier;
-
- private boolean mHasCenterCutout;
- private boolean mConfigShowBatteryEstimate;
-
- private boolean mUseCombinedQSHeader;
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
}
- /**
- * How much the view containing the clock and QQS will translate down when QS is fully expanded.
- *
- * This matches the measured height of the view containing the date and privacy icons.
- */
- public int getOffsetTranslation() {
- return mTopViewMeasureHeight;
- }
-
@Override
protected void onFinishInflate() {
super.onFinishInflate();
-
mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
- mDatePrivacyView = findViewById(R.id.quick_status_bar_date_privacy);
- mStatusIconsView = findViewById(R.id.quick_qs_status_icons);
- mQSCarriers = findViewById(R.id.carrier_group);
- mContainer = findViewById(R.id.qs_container);
- mIconContainer = findViewById(R.id.statusIcons);
- mPrivacyChip = findViewById(R.id.privacy_chip);
- mDateView = findViewById(R.id.date);
- mClockDateView = findViewById(R.id.date_clock);
- mClockIconsSeparator = findViewById(R.id.separator);
- mRightLayout = findViewById(R.id.rightLayout);
- mDateContainer = findViewById(R.id.date_container);
- mPrivacyContainer = findViewById(R.id.privacy_container);
-
- mClockContainer = findViewById(R.id.clock_container);
- mClockView = findViewById(R.id.clock);
- mDatePrivacySeparator = findViewById(R.id.space);
- // Tint for the battery icons are handled in setupHost()
- mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
updateResources();
- Configuration config = mContext.getResources().getConfiguration();
- setDatePrivacyContainersWidth(config.orientation == Configuration.ORIENTATION_LANDSCAPE);
-
- updateBatteryMode();
-
- mIconsAlphaAnimatorFixed = new TouchAnimator.Builder()
- .addFloat(mIconContainer, "alpha", 0, 1)
- .addFloat(mBatteryRemainingIcon, "alpha", 0, 1)
- .build();
- }
-
- void onAttach(TintedIconManager iconManager,
- QSExpansionPathInterpolator qsExpansionPathInterpolator,
- List<String> rssiIgnoredSlots,
- StatusBarContentInsetsProvider insetsProvider,
- boolean useCombinedQSHeader) {
- mUseCombinedQSHeader = useCombinedQSHeader;
- mTintedIconManager = iconManager;
- mRssiIgnoredSlots = rssiIgnoredSlots;
- mInsetsProvider = insetsProvider;
- int fillColor = Utils.getColorAttrDefaultColor(getContext(),
- android.R.attr.textColorPrimary);
-
- // Set the correct tint for the status icons so they contrast
- iconManager.setTint(fillColor);
-
- mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
- updateAnimators();
- }
-
- void setIsSingleCarrier(boolean isSingleCarrier) {
- mIsSingleCarrier = isSingleCarrier;
- updateAlphaAnimator();
- }
-
- public QuickQSPanel getHeaderQsPanel() {
- return mHeaderQsPanel;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (mDatePrivacyView.getMeasuredHeight() != mTopViewMeasureHeight) {
- mTopViewMeasureHeight = mDatePrivacyView.getMeasuredHeight();
- post(this::updateAnimators);
- }
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateResources();
- setDatePrivacyContainersWidth(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE);
- }
-
- @Override
- public void onRtlPropertiesChanged(int layoutDirection) {
- super.onRtlPropertiesChanged(layoutDirection);
- updateResources();
- }
-
- private void setDatePrivacyContainersWidth(boolean landscape) {
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mDateContainer.getLayoutParams();
- lp.width = landscape ? WRAP_CONTENT : 0;
- lp.weight = landscape ? 0f : 1f;
- mDateContainer.setLayoutParams(lp);
-
- lp = (LinearLayout.LayoutParams) mPrivacyContainer.getLayoutParams();
- lp.width = landscape ? WRAP_CONTENT : 0;
- lp.weight = landscape ? 0f : 1f;
- mPrivacyContainer.setLayoutParams(lp);
- }
-
- private void updateBatteryMode() {
- if (mConfigShowBatteryEstimate && !mHasCenterCutout) {
- mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
- } else {
- mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ON);
- }
}
@Override
public boolean onTouchEvent(MotionEvent event) {
- // If using combined headers, only react to touches inside QuickQSPanel
- if (!mUseCombinedQSHeader || event.getY() > mHeaderQsPanel.getTop()) {
+ // Only react to touches inside QuickQSPanel
+ if (event.getY() > mHeaderQsPanel.getTop()) {
return super.onTouchEvent(event);
} else {
return false;
@@ -245,193 +73,29 @@ public class QuickStatusBarHeader extends FrameLayout {
boolean largeScreenHeaderActive =
LargeScreenUtils.shouldUseLargeScreenShadeHeader(resources);
- boolean gone = largeScreenHeaderActive || mUseCombinedQSHeader || mQsDisabled;
- mStatusIconsView.setVisibility(gone ? View.GONE : View.VISIBLE);
- mDatePrivacyView.setVisibility(gone ? View.GONE : View.VISIBLE);
-
- mConfigShowBatteryEstimate = resources.getBoolean(R.bool.config_showBatteryEstimateQSBH);
-
- mRoundedCornerPadding = resources.getDimensionPixelSize(
- R.dimen.rounded_corner_content_padding);
-
- int qsOffsetHeight = SystemBarUtils.getQuickQsOffsetHeight(mContext);
-
- mDatePrivacyView.getLayoutParams().height =
- Math.max(qsOffsetHeight, mDatePrivacyView.getMinimumHeight());
- mDatePrivacyView.setLayoutParams(mDatePrivacyView.getLayoutParams());
-
- mStatusIconsView.getLayoutParams().height =
- Math.max(qsOffsetHeight, mStatusIconsView.getMinimumHeight());
- mStatusIconsView.setLayoutParams(mStatusIconsView.getLayoutParams());
-
ViewGroup.LayoutParams lp = getLayoutParams();
if (mQsDisabled) {
- lp.height = mStatusIconsView.getLayoutParams().height;
+ lp.height = 0;
} else {
lp.height = WRAP_CONTENT;
}
setLayoutParams(lp);
- int textColor = Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorPrimary);
- if (textColor != mTextColorPrimary) {
- int textColorSecondary = Utils.getColorAttrDefaultColor(mContext,
- android.R.attr.textColorSecondary);
- mTextColorPrimary = textColor;
- mClockView.setTextColor(textColor);
- if (mTintedIconManager != null) {
- mTintedIconManager.setTint(textColor);
- }
- mBatteryRemainingIcon.updateColors(mTextColorPrimary, textColorSecondary,
- mTextColorPrimary);
- }
-
MarginLayoutParams qqsLP = (MarginLayoutParams) mHeaderQsPanel.getLayoutParams();
if (largeScreenHeaderActive) {
qqsLP.topMargin = mContext.getResources()
.getDimensionPixelSize(R.dimen.qqs_layout_margin_top);
- } else if (!mUseCombinedQSHeader) {
- qqsLP.topMargin = qsOffsetHeight;
} else {
qqsLP.topMargin = mContext.getResources()
.getDimensionPixelSize(R.dimen.large_screen_shade_header_min_height);
}
mHeaderQsPanel.setLayoutParams(qqsLP);
-
- updateBatteryMode();
- updateHeadersPadding();
- updateAnimators();
-
- updateClockDatePadding();
}
- private void updateClockDatePadding() {
- int startPadding = mContext.getResources()
- .getDimensionPixelSize(R.dimen.status_bar_left_clock_starting_padding);
- int endPadding = mContext.getResources()
- .getDimensionPixelSize(R.dimen.status_bar_left_clock_end_padding);
- mClockView.setPaddingRelative(
- startPadding,
- mClockView.getPaddingTop(),
- endPadding,
- mClockView.getPaddingBottom()
- );
-
- MarginLayoutParams lp = (MarginLayoutParams) mClockDateView.getLayoutParams();
- lp.setMarginStart(endPadding);
- mClockDateView.setLayoutParams(lp);
- }
-
- private void updateAnimators() {
- if (mUseCombinedQSHeader) {
- mTranslationAnimator = null;
- return;
- }
- updateAlphaAnimator();
- int offset = mTopViewMeasureHeight;
-
- mTranslationAnimator = new TouchAnimator.Builder()
- .addFloat(mContainer, "translationY", 0, offset)
- .setInterpolator(mQSExpansionPathInterpolator != null
- ? mQSExpansionPathInterpolator.getYInterpolator()
- : null)
- .build();
- }
-
- private void updateAlphaAnimator() {
- if (mUseCombinedQSHeader) {
- mAlphaAnimator = null;
- return;
- }
- TouchAnimator.Builder builder = new TouchAnimator.Builder()
- // These views appear on expanding down
- .addFloat(mDateView, "alpha", 0, 0, 1)
- .addFloat(mClockDateView, "alpha", 1, 0, 0)
- .addFloat(mQSCarriers, "alpha", 0, 1)
- .setListener(new TouchAnimator.ListenerAdapter() {
- @Override
- public void onAnimationAtEnd() {
- super.onAnimationAtEnd();
- if (!mIsSingleCarrier) {
- mIconContainer.addIgnoredSlots(mRssiIgnoredSlots);
- }
- // Make it gone so there's enough room for carrier names
- mClockDateView.setVisibility(View.GONE);
- }
-
- @Override
- public void onAnimationStarted() {
- mClockDateView.setVisibility(View.VISIBLE);
- mClockDateView.setFreezeSwitching(true);
- setSeparatorVisibility(false);
- if (!mIsSingleCarrier) {
- mIconContainer.addIgnoredSlots(mRssiIgnoredSlots);
- }
- }
-
- @Override
- public void onAnimationAtStart() {
- super.onAnimationAtStart();
- mClockDateView.setFreezeSwitching(false);
- mClockDateView.setVisibility(View.VISIBLE);
- setSeparatorVisibility(mShowClockIconsSeparator);
- // In QQS we never ignore RSSI.
- mIconContainer.removeIgnoredSlots(mRssiIgnoredSlots);
- }
- });
- mAlphaAnimator = builder.build();
- }
-
- void setChipVisibility(boolean visibility) {
- if (visibility) {
- // Animates the icons and battery indicator from alpha 0 to 1, when the chip is visible
- mIconsAlphaAnimator = mIconsAlphaAnimatorFixed;
- mIconsAlphaAnimator.setPosition(mKeyguardExpansionFraction);
- } else {
- mIconsAlphaAnimator = null;
- mIconContainer.setAlpha(1);
- mBatteryRemainingIcon.setAlpha(1);
- }
-
- }
-
- /** */
public void setExpanded(boolean expanded, QuickQSPanelController quickQSPanelController) {
if (mExpanded == expanded) return;
mExpanded = expanded;
quickQSPanelController.setExpanded(expanded);
- updateEverything();
- }
-
- /**
- * Animates the inner contents based on the given expansion details.
- *
- * @param forceExpanded whether we should show the state expanded forcibly
- * @param expansionFraction how much the QS panel is expanded/pulled out (up to 1f)
- * @param panelTranslationY how much the panel has physically moved down vertically (required
- * for keyguard animations only)
- */
- public void setExpansion(boolean forceExpanded, float expansionFraction,
- float panelTranslationY) {
- final float keyguardExpansionFraction = forceExpanded ? 1f : expansionFraction;
-
- if (mAlphaAnimator != null) {
- mAlphaAnimator.setPosition(keyguardExpansionFraction);
- }
- if (mTranslationAnimator != null) {
- mTranslationAnimator.setPosition(keyguardExpansionFraction);
- }
- if (mIconsAlphaAnimator != null) {
- mIconsAlphaAnimator.setPosition(keyguardExpansionFraction);
- }
- // If forceExpanded (we are opening QS from lockscreen), the animators have been set to
- // position = 1f.
- if (forceExpanded) {
- setAlpha(expansionFraction);
- } else {
- setAlpha(1);
- }
-
- mKeyguardExpansionFraction = keyguardExpansionFraction;
}
public void disable(int state1, int state2, boolean animate) {
@@ -439,133 +103,13 @@ public class QuickStatusBarHeader extends FrameLayout {
if (disabled == mQsDisabled) return;
mQsDisabled = disabled;
mHeaderQsPanel.setDisabledByPolicy(disabled);
- mStatusIconsView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
updateResources();
}
- @Override
- public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- // Handle padding of the views
- DisplayCutout cutout = insets.getDisplayCutout();
-
- Pair<Integer, Integer> sbInsets = mInsetsProvider
- .getStatusBarContentInsetsForCurrentRotation();
- boolean hasCornerCutout = mInsetsProvider.currentRotationHasCornerCutout();
-
- mDatePrivacyView.setPadding(sbInsets.first, 0, sbInsets.second, 0);
- mStatusIconsView.setPadding(sbInsets.first, 0, sbInsets.second, 0);
- LinearLayout.LayoutParams datePrivacySeparatorLayoutParams =
- (LinearLayout.LayoutParams) mDatePrivacySeparator.getLayoutParams();
- LinearLayout.LayoutParams mClockIconsSeparatorLayoutParams =
- (LinearLayout.LayoutParams) mClockIconsSeparator.getLayoutParams();
-
- Rect topCutout = cutout == null ? null : cutout.getBoundingRectTop();
- if (topCutout == null || topCutout.isEmpty() || hasCornerCutout) {
- datePrivacySeparatorLayoutParams.width = 0;
- mDatePrivacySeparator.setVisibility(View.GONE);
- mClockIconsSeparatorLayoutParams.width = 0;
- setSeparatorVisibility(false);
- mShowClockIconsSeparator = false;
- mHasCenterCutout = false;
- } else {
- datePrivacySeparatorLayoutParams.width = topCutout.width();
- mDatePrivacySeparator.setVisibility(View.VISIBLE);
- mClockIconsSeparatorLayoutParams.width = topCutout.width();
- mShowClockIconsSeparator = true;
- setSeparatorVisibility(mKeyguardExpansionFraction == 0f);
- mHasCenterCutout = true;
- }
-
- mDatePrivacySeparator.setLayoutParams(datePrivacySeparatorLayoutParams);
- mClockIconsSeparator.setLayoutParams(mClockIconsSeparatorLayoutParams);
- mCutOutPaddingLeft = sbInsets.first;
- mCutOutPaddingRight = sbInsets.second;
- mWaterfallTopInset = cutout == null ? 0 : cutout.getWaterfallInsets().top;
-
- updateBatteryMode();
- updateHeadersPadding();
- return super.onApplyWindowInsets(insets);
- }
-
- /**
- * Sets the visibility of the separator between clock and icons.
- *
- * This separator is "visible" when there is a center cutout, to block that space. In that
- * case, the clock and the layout on the right (containing the icons and the battery meter) are
- * set to weight 1 to take the available space.
- * @param visible whether the separator between clock and icons should be visible.
- */
- private void setSeparatorVisibility(boolean visible) {
- int newVisibility = visible ? View.VISIBLE : View.GONE;
- if (mClockIconsSeparator.getVisibility() == newVisibility) return;
-
- mClockIconsSeparator.setVisibility(visible ? View.VISIBLE : View.GONE);
- mQSCarriers.setVisibility(visible ? View.GONE : View.VISIBLE);
-
- LinearLayout.LayoutParams lp =
- (LinearLayout.LayoutParams) mClockContainer.getLayoutParams();
- lp.width = visible ? 0 : WRAP_CONTENT;
- lp.weight = visible ? 1f : 0f;
- mClockContainer.setLayoutParams(lp);
-
- lp = (LinearLayout.LayoutParams) mRightLayout.getLayoutParams();
- lp.width = visible ? 0 : WRAP_CONTENT;
- lp.weight = visible ? 1f : 0f;
- mRightLayout.setLayoutParams(lp);
- }
-
- private void updateHeadersPadding() {
- setContentMargins(mDatePrivacyView, 0, 0);
- setContentMargins(mStatusIconsView, 0, 0);
- int paddingLeft = 0;
- int paddingRight = 0;
-
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
- int leftMargin = lp.leftMargin;
- int rightMargin = lp.rightMargin;
-
- // The clock might collide with cutouts, let's shift it out of the way.
- // We only do that if the inset is bigger than our own padding, since it's nicer to
- // align with
- if (mCutOutPaddingLeft > 0) {
- // if there's a cutout, let's use at least the rounded corner inset
- int cutoutPadding = Math.max(mCutOutPaddingLeft, mRoundedCornerPadding);
- paddingLeft = Math.max(cutoutPadding - leftMargin, 0);
- }
- if (mCutOutPaddingRight > 0) {
- // if there's a cutout, let's use at least the rounded corner inset
- int cutoutPadding = Math.max(mCutOutPaddingRight, mRoundedCornerPadding);
- paddingRight = Math.max(cutoutPadding - rightMargin, 0);
- }
-
- mDatePrivacyView.setPadding(paddingLeft,
- mWaterfallTopInset,
- paddingRight,
- 0);
- mStatusIconsView.setPadding(paddingLeft,
- mWaterfallTopInset,
- paddingRight,
- 0);
- }
-
- public void updateEverything() {
- post(() -> setClickable(!mExpanded));
- }
-
private void setContentMargins(View view, int marginStart, int marginEnd) {
MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
lp.setMarginStart(marginStart);
lp.setMarginEnd(marginEnd);
view.setLayoutParams(lp);
}
-
- /**
- * Scroll the headers away.
- *
- * @param scrollY the scroll of the QSPanel container
- */
- public void setExpandedScrollAmount(int scrollY) {
- mStatusIconsView.setScrollY(scrollY);
- mDatePrivacyView.setScrollY(scrollY);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index ccaab1adaf26..64960e6ce23e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -16,154 +16,38 @@
package com.android.systemui.qs;
-import android.os.Bundle;
-
-import com.android.internal.colorextraction.ColorExtractor;
-import com.android.systemui.R;
-import com.android.systemui.battery.BatteryMeterViewController;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.demomode.DemoMode;
-import com.android.systemui.demomode.DemoModeController;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
-import com.android.systemui.qs.carrier.QSCarrierGroupController;
import com.android.systemui.qs.dagger.QSScope;
-import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarLocation;
-import com.android.systemui.statusbar.phone.StatusIconContainer;
-import com.android.systemui.statusbar.policy.Clock;
-import com.android.systemui.statusbar.policy.VariableDateViewController;
import com.android.systemui.util.ViewController;
-import java.util.List;
-
import javax.inject.Inject;
/**
* Controller for {@link QuickStatusBarHeader}.
*/
@QSScope
-class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> implements
- ChipVisibilityListener {
+class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> {
- private final QSCarrierGroupController mQSCarrierGroupController;
private final QuickQSPanelController mQuickQSPanelController;
- private final Clock mClockView;
- private final StatusBarIconController mStatusBarIconController;
- private final DemoModeController mDemoModeController;
- private final StatusIconContainer mIconContainer;
- private final StatusBarIconController.TintedIconManager mIconManager;
- private final DemoMode mDemoModeReceiver;
- private final QSExpansionPathInterpolator mQSExpansionPathInterpolator;
- private final FeatureFlags mFeatureFlags;
- private final BatteryMeterViewController mBatteryMeterViewController;
- private final StatusBarContentInsetsProvider mInsetsProvider;
-
- private final VariableDateViewController mVariableDateViewControllerDateView;
- private final VariableDateViewController mVariableDateViewControllerClockDateView;
- private final HeaderPrivacyIconsController mPrivacyIconsController;
-
private boolean mListening;
- private SysuiColorExtractor mColorExtractor;
- private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
-
@Inject
QuickStatusBarHeaderController(QuickStatusBarHeader view,
- HeaderPrivacyIconsController headerPrivacyIconsController,
- StatusBarIconController statusBarIconController,
- DemoModeController demoModeController,
- QuickQSPanelController quickQSPanelController,
- QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder,
- SysuiColorExtractor colorExtractor,
- QSExpansionPathInterpolator qsExpansionPathInterpolator,
- FeatureFlags featureFlags,
- VariableDateViewController.Factory variableDateViewControllerFactory,
- BatteryMeterViewController batteryMeterViewController,
- StatusBarContentInsetsProvider statusBarContentInsetsProvider,
- StatusBarIconController.TintedIconManager.Factory tintedIconManagerFactory) {
+ QuickQSPanelController quickQSPanelController
+ ) {
super(view);
- mPrivacyIconsController = headerPrivacyIconsController;
- mStatusBarIconController = statusBarIconController;
- mDemoModeController = demoModeController;
mQuickQSPanelController = quickQSPanelController;
- mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
- mFeatureFlags = featureFlags;
- mBatteryMeterViewController = batteryMeterViewController;
- mInsetsProvider = statusBarContentInsetsProvider;
-
- mQSCarrierGroupController = qsCarrierGroupControllerBuilder
- .setQSCarrierGroup(mView.findViewById(R.id.carrier_group))
- .build();
- mClockView = mView.findViewById(R.id.clock);
- mIconContainer = mView.findViewById(R.id.statusIcons);
- mVariableDateViewControllerDateView = variableDateViewControllerFactory.create(
- mView.requireViewById(R.id.date)
- );
- mVariableDateViewControllerClockDateView = variableDateViewControllerFactory.create(
- mView.requireViewById(R.id.date_clock)
- );
-
- mIconManager = tintedIconManagerFactory.create(mIconContainer, StatusBarLocation.QS);
- mDemoModeReceiver = new ClockDemoModeReceiver(mClockView);
- mColorExtractor = colorExtractor;
- mOnColorsChangedListener = (extractor, which) -> {
- final boolean lightTheme = mColorExtractor.getNeutralColors().supportsDarkText();
- mClockView.onColorsChanged(lightTheme);
- };
- mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
-
- // Don't need to worry about tuner settings for this icon
- mBatteryMeterViewController.ignoreTunerUpdates();
- }
-
- @Override
- protected void onInit() {
- mBatteryMeterViewController.init();
}
@Override
protected void onViewAttached() {
- mPrivacyIconsController.onParentVisible();
- mPrivacyIconsController.setChipVisibilityListener(this);
- mIconContainer.addIgnoredSlot(
- getResources().getString(com.android.internal.R.string.status_bar_managed_profile));
- mIconContainer.addIgnoredSlot(
- getResources().getString(com.android.internal.R.string.status_bar_alarm_clock));
- mIconContainer.setShouldRestrictIcons(false);
- mStatusBarIconController.addIconGroup(mIconManager);
-
- mView.setIsSingleCarrier(mQSCarrierGroupController.isSingleCarrier());
- mQSCarrierGroupController
- .setOnSingleCarrierChangedListener(mView::setIsSingleCarrier);
-
- List<String> rssiIgnoredSlots = List.of(
- getResources().getString(com.android.internal.R.string.status_bar_mobile)
- );
-
- mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots,
- mInsetsProvider, mFeatureFlags.isEnabled(Flags.COMBINED_QS_HEADERS));
-
- mDemoModeController.addCallback(mDemoModeReceiver);
-
- mVariableDateViewControllerDateView.init();
- mVariableDateViewControllerClockDateView.init();
}
@Override
protected void onViewDetached() {
- mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener);
- mPrivacyIconsController.onParentInvisible();
- mStatusBarIconController.removeIconGroup(mIconManager);
- mQSCarrierGroupController.setOnSingleCarrierChangedListener(null);
- mDemoModeController.removeCallback(mDemoModeReceiver);
setListening(false);
}
public void setListening(boolean listening) {
- mQSCarrierGroupController.setListening(listening);
-
if (listening == mListening) {
return;
}
@@ -174,48 +58,9 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
if (mQuickQSPanelController.switchTileLayout(false)) {
mView.updateResources();
}
-
- if (listening) {
- mPrivacyIconsController.startListening();
- } else {
- mPrivacyIconsController.stopListening();
- }
- }
-
- @Override
- public void onChipVisibilityRefreshed(boolean visible) {
- mView.setChipVisibility(visible);
}
public void setContentMargins(int marginStart, int marginEnd) {
mQuickQSPanelController.setContentMargins(marginStart, marginEnd);
}
-
- private static class ClockDemoModeReceiver implements DemoMode {
- private Clock mClockView;
-
- @Override
- public List<String> demoCommands() {
- return List.of(COMMAND_CLOCK);
- }
-
- ClockDemoModeReceiver(Clock clockView) {
- mClockView = clockView;
- }
-
- @Override
- public void dispatchDemoCommand(String command, Bundle args) {
- mClockView.dispatchDemoCommand(command, args);
- }
-
- @Override
- public void onDemoModeStarted() {
- mClockView.onDemoModeStarted();
- }
-
- @Override
- public void onDemoModeFinished() {
- mClockView.onDemoModeFinished();
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
index 97390112c3ed..a319fb8d8756 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -40,7 +40,7 @@ import com.android.systemui.plugins.qs.QSContainerController;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSEditEvent;
import com.android.systemui.qs.QSFragment;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -57,7 +57,7 @@ import javax.inject.Inject;
@QSScope
public class QSCustomizerController extends ViewController<QSCustomizer> {
private final TileQueryHelper mTileQueryHelper;
- private final QSTileHost mQsTileHost;
+ private final QSHost mQsHost;
private final TileAdapter mTileAdapter;
private final ScreenLifecycle mScreenLifecycle;
private final KeyguardStateController mKeyguardStateController;
@@ -104,12 +104,12 @@ public class QSCustomizerController extends ViewController<QSCustomizer> {
@Inject
protected QSCustomizerController(QSCustomizer view, TileQueryHelper tileQueryHelper,
- QSTileHost qsTileHost, TileAdapter tileAdapter, ScreenLifecycle screenLifecycle,
+ QSHost qsHost, TileAdapter tileAdapter, ScreenLifecycle screenLifecycle,
KeyguardStateController keyguardStateController, LightBarController lightBarController,
ConfigurationController configurationController, UiEventLogger uiEventLogger) {
super(view);
mTileQueryHelper = tileQueryHelper;
- mQsTileHost = qsTileHost;
+ mQsHost = qsHost;
mTileAdapter = tileAdapter;
mScreenLifecycle = screenLifecycle;
mKeyguardStateController = keyguardStateController;
@@ -175,7 +175,7 @@ public class QSCustomizerController extends ViewController<QSCustomizer> {
private void reset() {
- mTileAdapter.resetTileSpecs(QSTileHost.getDefaultSpecs(getContext()));
+ mTileAdapter.resetTileSpecs(QSHost.getDefaultSpecs(getContext()));
}
public boolean isCustomizing() {
@@ -192,7 +192,7 @@ public class QSCustomizerController extends ViewController<QSCustomizer> {
mView.show(x, y, mTileAdapter);
mUiEventLogger.log(QSEditEvent.QS_EDIT_OPEN);
}
- mTileQueryHelper.queryTiles(mQsTileHost);
+ mTileQueryHelper.queryTiles(mQsHost);
mKeyguardStateController.addCallback(mKeyguardCallback);
mView.updateNavColors(mLightBarController);
}
@@ -258,13 +258,13 @@ public class QSCustomizerController extends ViewController<QSCustomizer> {
private void save() {
if (mTileQueryHelper.isFinished()) {
- mTileAdapter.saveSpecs(mQsTileHost);
+ mTileAdapter.saveSpecs(mQsHost);
}
}
private void setTileSpecs() {
List<String> specs = new ArrayList<>();
- for (QSTile tile : mQsTileHost.getTiles()) {
+ for (QSTile tile : mQsHost.getTiles()) {
specs.add(tile.getTileSpec());
}
mTileAdapter.setTileSpecs(specs);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index d84b12c714bd..6a05684a74e8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -45,7 +45,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.qs.QSEditEvent;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.customize.TileAdapter.Holder;
import com.android.systemui.qs.customize.TileQueryHelper.TileInfo;
import com.android.systemui.qs.customize.TileQueryHelper.TileStateListener;
@@ -91,7 +91,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
private ItemDecoration mDecoration;
private final MarginTileDecoration mMarginDecoration;
private final int mMinNumTiles;
- private final QSTileHost mHost;
+ private final QSHost mHost;
private int mEditIndex;
private int mTileDividerIndex;
private int mFocusIndex;
@@ -117,7 +117,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
@Inject
public TileAdapter(
@QSThemedContext Context context,
- QSTileHost qsHost,
+ QSHost qsHost,
UiEventLogger uiEventLogger) {
mContext = context;
mHost = qsHost;
@@ -176,7 +176,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
mMarginDecoration.setHalfMargin(halfMargin);
}
- public void saveSpecs(QSTileHost host) {
+ public void saveSpecs(QSHost host) {
List<String> newSpecs = new ArrayList<>();
clearAccessibilityState();
for (int i = 1; i < mTiles.size() && mTiles.get(i) != null; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 32a7916da70f..d9f448493591 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -38,7 +38,7 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon;
@@ -85,7 +85,7 @@ public class TileQueryHelper {
mListener = listener;
}
- public void queryTiles(QSTileHost host) {
+ public void queryTiles(QSHost host) {
mTiles.clear();
mSpecs.clear();
mFinished = false;
@@ -97,7 +97,7 @@ public class TileQueryHelper {
return mFinished;
}
- private void addCurrentAndStockTiles(QSTileHost host) {
+ private void addCurrentAndStockTiles(QSHost host) {
String stock = mContext.getString(R.string.quick_settings_tiles_stock);
String current = Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.QS_TILES);
@@ -153,14 +153,14 @@ public class TileQueryHelper {
private class TileCollector implements QSTile.Callback {
private final List<TilePair> mQSTileList = new ArrayList<>();
- private final QSTileHost mQSTileHost;
+ private final QSHost mQSHost;
- TileCollector(List<QSTile> tilesToAdd, QSTileHost host) {
+ TileCollector(List<QSTile> tilesToAdd, QSHost host) {
for (QSTile tile: tilesToAdd) {
TilePair pair = new TilePair(tile);
mQSTileList.add(pair);
}
- mQSTileHost = host;
+ mQSHost = host;
if (tilesToAdd.isEmpty()) {
mBgExecutor.execute(this::finished);
}
@@ -168,7 +168,7 @@ public class TileQueryHelper {
private void finished() {
notifyTilesChanged(false);
- addPackageTiles(mQSTileHost);
+ addPackageTiles(mQSHost);
}
private void startListening() {
@@ -207,7 +207,7 @@ public class TileQueryHelper {
}
}
- private void addPackageTiles(final QSTileHost host) {
+ private void addPackageTiles(final QSHost host) {
mBgExecutor.execute(() -> {
Collection<QSTile> params = host.getTiles();
PackageManager pm = mContext.getPackageManager();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index 01eb636f75d6..ce6b8d499ee0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -24,10 +24,8 @@ import android.view.LayoutInflater;
import android.view.View;
import com.android.systemui.R;
-import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.privacy.OngoingPrivacyChip;
import com.android.systemui.qs.QSContainerImpl;
import com.android.systemui.qs.QSFooter;
import com.android.systemui.qs.QSFooterView;
@@ -37,7 +35,6 @@ import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.QuickStatusBarHeader;
import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.statusbar.phone.StatusIconContainer;
import javax.inject.Named;
@@ -106,12 +103,6 @@ public interface QSFragmentModule {
/** */
@Provides
- static BatteryMeterView providesBatteryMeterView(QuickStatusBarHeader quickStatusBarHeader) {
- return quickStatusBarHeader.findViewById(R.id.batteryRemainingIcon);
- }
-
- /** */
- @Provides
static QSFooterView providesQSFooterView(@RootView View view) {
return view.findViewById(R.id.qs_footer);
}
@@ -144,18 +135,4 @@ public interface QSFragmentModule {
static boolean providesQSUsingCollapsedLandscapeMedia(Context context) {
return useCollapsedMediaInLandscape(context.getResources());
}
-
- /** */
- @Provides
- @QSScope
- static OngoingPrivacyChip providesPrivacyChip(QuickStatusBarHeader qsHeader) {
- return qsHeader.findViewById(R.id.privacy_chip);
- }
-
- /** */
- @Provides
- @QSScope
- static StatusIconContainer providesStatusIconContainer(QuickStatusBarHeader qsHeader) {
- return qsHeader.findViewById(R.id.statusIcons);
- }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index 27ae1710467b..431d6e847207 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -67,7 +67,7 @@ public interface QSModule {
static AutoTileManager provideAutoTileManager(
Context context,
AutoAddTracker.Builder autoAddTrackerBuilder,
- QSTileHost host,
+ QSHost host,
@Background Handler handler,
SecureSettings secureSettings,
HotspotController hotspotController,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 7c2536dac56e..d4854e1a7daf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -328,7 +328,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
if (listening) {
updateDefaultTileAndIcon();
refreshState();
- if (!mServiceManager.isActiveTile()) {
+ if (!mServiceManager.isActiveTile() || !isTileReady()) {
mServiceManager.setBindRequested(true);
mService.onStartListening();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index e86bd7a30490..9f93e4926532 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -76,7 +76,8 @@ public class TileServiceManager {
this(tileServices, handler, userTracker, new TileLifecycleManager(handler,
tileServices.getContext(), tileServices,
new PackageManagerAdapter(tileServices.getContext()), broadcastDispatcher,
- new Intent().setComponent(component), userTracker.getUserHandle()));
+ new Intent(TileService.ACTION_QS_TILE).setComponent(component),
+ userTracker.getUserHandle()));
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
index 237b66e79ee5..d9e5580fc14c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
@@ -25,13 +25,13 @@ import android.os.RemoteException
import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.internal.statusbar.IAddTileResultCallback
+import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
+import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.R
-import com.android.systemui.statusbar.CommandQueue
import java.io.PrintWriter
import java.util.concurrent.atomic.AtomicBoolean
import java.util.function.Consumer
@@ -40,14 +40,14 @@ import javax.inject.Inject
private const val TAG = "TileServiceRequestController"
/**
- * Controller to interface between [TileRequestDialog] and [QSTileHost].
+ * Controller to interface between [TileRequestDialog] and [QSHost].
*/
class TileServiceRequestController constructor(
- private val qsTileHost: QSTileHost,
+ private val qsHost: QSHost,
private val commandQueue: CommandQueue,
private val commandRegistry: CommandRegistry,
private val eventLogger: TileRequestDialogEventLogger,
- private val dialogCreator: () -> TileRequestDialog = { TileRequestDialog(qsTileHost.context) }
+ private val dialogCreator: () -> TileRequestDialog = { TileRequestDialog(qsHost.context) }
) {
companion object {
@@ -93,7 +93,7 @@ class TileServiceRequestController constructor(
}
private fun addTile(componentName: ComponentName) {
- qsTileHost.addTile(componentName, true)
+ qsHost.addTile(componentName, true)
}
@VisibleForTesting
@@ -158,7 +158,7 @@ class TileServiceRequestController constructor(
private fun isTileAlreadyAdded(componentName: ComponentName): Boolean {
val spec = CustomTile.toSpec(componentName)
- return qsTileHost.indexOf(spec) != -1
+ return qsHost.indexOf(spec) != -1
}
inner class TileServiceRequestCommand : Command {
@@ -194,13 +194,13 @@ class TileServiceRequestController constructor(
private val commandQueue: CommandQueue,
private val commandRegistry: CommandRegistry
) {
- fun create(qsTileHost: QSTileHost): TileServiceRequestController {
+ fun create(qsHost: QSHost): TileServiceRequestController {
return TileServiceRequestController(
- qsTileHost,
+ qsHost,
commandQueue,
commandRegistry,
TileRequestDialogEventLogger()
)
}
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 84a18d8dd365..adc71657e680 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -39,7 +39,7 @@ import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -68,22 +68,24 @@ public class TileServices extends IQSService.Stub {
private final Context mContext;
private final Handler mMainHandler;
private final Provider<Handler> mHandlerProvider;
- private final QSTileHost mHost;
+ private final QSHost mHost;
private final KeyguardStateController mKeyguardStateController;
private final BroadcastDispatcher mBroadcastDispatcher;
private final CommandQueue mCommandQueue;
private final UserTracker mUserTracker;
+ private final StatusBarIconController mStatusBarIconController;
private int mMaxBound = DEFAULT_MAX_BOUND;
@Inject
public TileServices(
- QSTileHost host,
+ QSHost host,
@Main Provider<Handler> handlerProvider,
BroadcastDispatcher broadcastDispatcher,
UserTracker userTracker,
KeyguardStateController keyguardStateController,
- CommandQueue commandQueue) {
+ CommandQueue commandQueue,
+ StatusBarIconController statusBarIconController) {
mHost = host;
mKeyguardStateController = keyguardStateController;
mContext = mHost.getContext();
@@ -92,6 +94,7 @@ public class TileServices extends IQSService.Stub {
mMainHandler = mHandlerProvider.get();
mUserTracker = userTracker;
mCommandQueue = commandQueue;
+ mStatusBarIconController = statusBarIconController;
mCommandQueue.addCallback(mRequestListeningCallback);
}
@@ -99,7 +102,7 @@ public class TileServices extends IQSService.Stub {
return mContext;
}
- public QSTileHost getHost() {
+ public QSHost getHost() {
return mHost;
}
@@ -131,8 +134,7 @@ public class TileServices extends IQSService.Stub {
mTiles.remove(tile.getComponent());
final String slot = tile.getComponent().getClassName();
// TileServices doesn't know how to add more than 1 icon per slot, so remove all
- mMainHandler.post(() -> mHost.getIconController()
- .removeAllIconsForExternalSlot(slot));
+ mMainHandler.post(() -> mStatusBarIconController.removeAllIconsForSlot(slot));
}
}
@@ -309,7 +311,7 @@ public class TileServices extends IQSService.Stub {
mMainHandler.post(new Runnable() {
@Override
public void run() {
- StatusBarIconController iconController = mHost.getIconController();
+ StatusBarIconController iconController = mStatusBarIconController;
iconController.setIcon(componentName.getClassName(), statusIcon);
iconController.setExternalIcon(componentName.getClassName());
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
index 03bb7a0f45da..8387c1dd60a5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
@@ -71,8 +71,8 @@ interface FooterActionsInteractor {
/**
* Show the device monitoring dialog, expanded from [expandable] if it's not null.
*
- * Important: [quickSettingsContext] *must* be the [Context] associated to the [Quick Settings
- * fragment][com.android.systemui.qs.QSFragment].
+ * Important: [quickSettingsContext] *must* be the [Context] associated to the
+ * [Quick Settings fragment][com.android.systemui.qs.QSFragment].
*/
fun showDeviceMonitoringDialog(quickSettingsContext: Context, expandable: Expandable?)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
index fbf32b3b99ea..f170ac1d9d4e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
@@ -196,9 +196,9 @@ class FooterActionsViewModel(
* Observe the device monitoring dialog requests and show the dialog accordingly. This function
* will suspend indefinitely and will need to be cancelled to stop observing.
*
- * Important: [quickSettingsContext] must be the [Context] associated to the [Quick Settings
- * fragment][com.android.systemui.qs.QSFragment], and the call to this function must be
- * cancelled when that fragment is destroyed.
+ * Important: [quickSettingsContext] must be the [Context] associated to the
+ * [Quick Settings fragment][com.android.systemui.qs.QSFragment], and the call to this function
+ * must be cancelled when that fragment is destroyed.
*/
suspend fun observeDeviceMonitoringDialogRequests(quickSettingsContext: Context) {
footerActionsInteractor.deviceMonitoringDialogRequests.collect {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
index d32ef327e90e..23c41db6d5a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
@@ -17,15 +17,14 @@
package com.android.systemui.qs.logging
import android.service.quicksettings.Tile
+import android.view.View
import com.android.systemui.log.dagger.QSLog
import com.android.systemui.plugins.log.ConstantStringsLogger
import com.android.systemui.plugins.log.ConstantStringsLoggerImpl
import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.plugins.log.LogLevel.DEBUG
import com.android.systemui.plugins.log.LogLevel.ERROR
import com.android.systemui.plugins.log.LogLevel.VERBOSE
-import com.android.systemui.plugins.log.LogMessage
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.statusbar.StatusBarState
import com.google.errorprone.annotations.CompileTimeConstant
@@ -332,4 +331,25 @@ class QSLogger @Inject constructor(@QSLog private val buffer: LogBuffer) :
else -> "wrong state"
}
}
+
+ fun logVisibility(viewName: String, @View.Visibility visibility: Int) {
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = viewName
+ str2 = toVisibilityString(visibility)
+ },
+ { "$str1 visibility: $str2" }
+ )
+ }
+
+ private fun toVisibilityString(visibility: Int): String {
+ return when (visibility) {
+ View.VISIBLE -> "VISIBLE"
+ View.INVISIBLE -> "INVISIBLE"
+ View.GONE -> "GONE"
+ else -> "undefined"
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 25ff308b46bb..019ca52107dd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -631,7 +631,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
final NavigationBarView navBarView =
mNavBarControllerLazy.get().getNavigationBarView(mContext.getDisplayId());
final NotificationPanelViewController panelController =
- mCentralSurfacesOptionalLazy.get().get().getNotificationPanelViewController();
+ mCentralSurfacesOptionalLazy.get()
+ .map(CentralSurfaces::getNotificationPanelViewController)
+ .orElse(null);
if (SysUiState.DEBUG) {
Log.d(TAG_OPS, "Updating sysui state flags: navBarFragment=" + navBarFragment
+ " navBarView=" + navBarView + " panelController=" + panelController);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 645b1256e5f1..346acf958e51 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -16,7 +16,7 @@
package com.android.systemui.recents;
-import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
+import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
@@ -265,7 +265,7 @@ public class ScreenPinningRequest implements View.OnClickListener,
.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
View buttons = mLayout.findViewById(R.id.screen_pinning_buttons);
if (!QuickStepContract.isGesturalMode(mNavBarMode)
- && hasSoftNavigationBar(mContext.getDisplayId()) && !isTablet(mContext)) {
+ && hasSoftNavigationBar(mContext.getDisplayId()) && !isLargeScreen(mContext)) {
buttons.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
swapChildrenIfRtlAndVertical(buttons);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
index dd21be971b36..30509e23d186 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
@@ -124,8 +124,9 @@ class ScreenRecordPermissionDialog(
/**
* Starts screen capture after some countdown
+ *
* @param captureTarget target to capture (could be e.g. a task) or null to record the whole
- * screen
+ * screen
*/
private fun requestScreenCapture(captureTarget: MediaProjectionCaptureTarget?) {
val userContext = userContextProvider.userContext
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
index 310baafbae1a..a8f99bef2423 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
@@ -70,7 +70,7 @@ object ActionIntentCreator {
/**
* @return an ACTION_EDIT intent for the given URI, directed to config_screenshotEditor if
- * available.
+ * available.
*/
fun createEditIntent(uri: Uri, context: Context): Intent {
val editIntent = Intent(Intent.ACTION_EDIT)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java b/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java
index ead3b7b1de53..0b4b7c691cfd 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java
@@ -45,6 +45,7 @@ public class DraggableConstraintLayout extends ConstraintLayout
implements ViewTreeObserver.OnComputeInternalInsetsListener {
private static final float VELOCITY_DP_PER_MS = 1;
+ private static final int MAXIMUM_DISMISS_DISTANCE_DP = 400;
private final SwipeDismissHandler mSwipeDismissHandler;
private final GestureDetector mSwipeDetector;
@@ -347,14 +348,18 @@ public class DraggableConstraintLayout extends ConstraintLayout
} else {
finalX = -1 * getBackgroundRight();
}
- float distance = Math.abs(finalX - startX);
+ float distance = Math.min(Math.abs(finalX - startX),
+ FloatingWindowUtil.dpToPx(mDisplayMetrics, MAXIMUM_DISMISS_DISTANCE_DP));
+ // ensure that view dismisses in the right direction (right in LTR, left in RTL)
+ float distanceVector = Math.copySign(distance, finalX - startX);
anim.addUpdateListener(animation -> {
- float translation = MathUtils.lerp(startX, finalX, animation.getAnimatedFraction());
+ float translation = MathUtils.lerp(
+ startX, startX + distanceVector, animation.getAnimatedFraction());
mView.setTranslationX(translation);
mView.setAlpha(1 - animation.getAnimatedFraction());
});
- anim.setDuration((long) (distance / Math.abs(velocity)));
+ anim.setDuration((long) (Math.abs(distance / velocity)));
return anim;
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
index c8c133774766..7cfe2327f992 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
@@ -57,7 +57,8 @@ import java.util.concurrent.Executor;
import javax.inject.Inject;
-class ImageExporter {
+/** A class to help with exporting screenshot to storage. */
+public class ImageExporter {
private static final String TAG = LogConfig.logTag(ImageExporter.class);
static final Duration PENDING_ENTRY_TTL = Duration.ofHours(24);
@@ -90,7 +91,7 @@ class ImageExporter {
private final FeatureFlags mFlags;
@Inject
- ImageExporter(ContentResolver resolver, FeatureFlags flags) {
+ public ImageExporter(ContentResolver resolver, FeatureFlags flags) {
mResolver = resolver;
mFlags = flags;
}
@@ -148,7 +149,7 @@ class ImageExporter {
*
* @return a listenable future result
*/
- ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap,
+ public ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap,
UserHandle owner) {
return export(executor, requestId, bitmap, ZonedDateTime.now(), owner);
}
@@ -181,13 +182,14 @@ class ImageExporter {
);
}
- static class Result {
- Uri uri;
- UUID requestId;
- String fileName;
- long timestamp;
- CompressFormat format;
- boolean published;
+ /** The result returned by the task exporting screenshots to storage. */
+ public static class Result {
+ public Uri uri;
+ public UUID requestId;
+ public String fileName;
+ public long timestamp;
+ public CompressFormat format;
+ public boolean published;
@Override
public String toString() {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 8721d71897f7..557e95c64443 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -419,6 +419,10 @@ public class ScreenshotController {
return;
}
+ mScreenBitmap = screenshot.getBitmap();
+ String oldPackageName = mPackageName;
+ mPackageName = screenshot.getPackageNameString();
+
if (!isUserSetupComplete(Process.myUserHandle())) {
Log.w(TAG, "User setup not complete, displaying toast only");
// User setup isn't complete, so we don't want to show any UI beyond a toast, as editing
@@ -433,10 +437,6 @@ public class ScreenshotController {
mScreenshotTakenInPortrait =
mContext.getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT;
- String oldPackageName = mPackageName;
- mPackageName = screenshot.getPackageNameString();
-
- mScreenBitmap = screenshot.getBitmap();
// Optimizations
mScreenBitmap.setHasAlpha(false);
mScreenBitmap.prepareToDraw();
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
index fc94aed5336a..7a62bae5b5ae 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
@@ -93,13 +93,7 @@ public enum ScreenshotEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "User has discarded the result of a long screenshot")
SCREENSHOT_LONG_SCREENSHOT_EXIT(911),
@UiEvent(doc = "A screenshot has been taken and saved to work profile")
- SCREENSHOT_SAVED_TO_WORK_PROFILE(1240),
- @UiEvent(doc = "Notes application triggered the screenshot for notes")
- SCREENSHOT_FOR_NOTE_TRIGGERED(1308),
- @UiEvent(doc = "User accepted the screenshot to be sent to the notes app")
- SCREENSHOT_FOR_NOTE_ACCEPTED(1309),
- @UiEvent(doc = "User cancelled the screenshot for notes app flow")
- SCREENSHOT_FOR_NOTE_CANCELLED(1310);
+ SCREENSHOT_SAVED_TO_WORK_PROFILE(1240);
private final int mId;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
index 1b728b8aa9cc..236213cb023f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
@@ -44,7 +44,7 @@ constructor(
/**
* @return a populated WorkProfileFirstRunData object if a work profile first run message should
- * be shown
+ * be shown
*/
fun onScreenshotTaken(userHandle: UserHandle?): WorkProfileFirstRunData? {
if (userHandle == null) return null
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
index 287e8101f86d..33a3125d1c68 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
@@ -19,6 +19,7 @@ package com.android.systemui.settings
import android.content.Context
import android.content.pm.UserInfo
import android.os.UserHandle
+import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
/**
@@ -67,14 +68,25 @@ interface UserTracker : UserContentResolverProvider, UserContextProvider {
interface Callback {
/**
+ * Same as {@link onUserChanging(Int, Context, CountDownLatch)} but the latch will be
+ * auto-decremented after the completion of this method.
+ */
+ @JvmDefault
+ fun onUserChanging(newUser: Int, userContext: Context) {}
+
+ /**
* Notifies that the current user is being changed.
* Override this method to run things while the screen is frozen for the user switch.
* Please use {@link #onUserChanged} if the task doesn't need to push the unfreezing of the
* screen further. Please be aware that code executed in this callback will lengthen the
- * user switch duration.
+ * user switch duration. When overriding this method, countDown() MUST be called on the
+ * latch once execution is complete.
*/
@JvmDefault
- fun onUserChanging(newUser: Int, userContext: Context) {}
+ fun onUserChanging(newUser: Int, userContext: Context, latch: CountDownLatch) {
+ onUserChanging(newUser, userContext)
+ latch.countDown()
+ }
/**
* Notifies that the current user has changed.
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 9f551c6ebd34..867403689292 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -183,9 +183,22 @@ class UserTrackerImpl internal constructor(
Log.i(TAG, "Switching to user $newUserId")
setUserIdInternal(newUserId)
- notifySubscribers {
- onUserChanging(newUserId, userContext)
- }.await()
+
+ val list = synchronized(callbacks) {
+ callbacks.toList()
+ }
+ val latch = CountDownLatch(list.size)
+ list.forEach {
+ val callback = it.callback.get()
+ if (callback != null) {
+ it.executor.execute {
+ callback.onUserChanging(userId, userContext, latch)
+ }
+ } else {
+ latch.countDown()
+ }
+ }
+ latch.await()
}
@WorkerThread
@@ -225,25 +238,18 @@ class UserTrackerImpl internal constructor(
}
}
- private inline fun notifySubscribers(
- crossinline action: UserTracker.Callback.() -> Unit
- ): CountDownLatch {
+ private inline fun notifySubscribers(crossinline action: UserTracker.Callback.() -> Unit) {
val list = synchronized(callbacks) {
callbacks.toList()
}
- val latch = CountDownLatch(list.size)
list.forEach {
if (it.callback.get() != null) {
it.executor.execute {
it.callback.get()?.action()
- latch.countDown()
}
- } else {
- latch.countDown()
}
}
- return latch
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
index e360ec20bd9b..a78b0aa97ea1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
@@ -31,7 +31,7 @@ operator fun ConstraintChange?.plus(other: ConstraintChange?): ConstraintChange?
/**
* Contains all changes that need to be performed to the different [ConstraintSet] in
- * [LargeScreenShadeHeaderController].
+ * [ShadeHeaderController].
*/
data class ConstraintsChanges(
val qqsConstraintsChanges: ConstraintChange? = null,
@@ -46,7 +46,7 @@ data class ConstraintsChanges(
}
/**
- * Determines [ConstraintChanges] for [LargeScreenShadeHeaderController] based on configurations.
+ * Determines [ConstraintChanges] for [ShadeHeaderController] based on configurations.
*
* Given that the number of different scenarios is not that large, having specific methods instead
* of a full map between state and [ConstraintSet] was preferred.
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
index 639172f9e37a..b445000c467d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
@@ -48,7 +48,10 @@ constructor(
setOf(
ViewIdToTranslate(R.id.quick_settings_panel, START, filterShade),
ViewIdToTranslate(R.id.notification_stack_scroller, END, filterShade),
- ViewIdToTranslate(R.id.rightLayout, END, filterShade),
+ ViewIdToTranslate(R.id.statusIcons, END, filterShade),
+ ViewIdToTranslate(R.id.privacy_container, END, filterShade),
+ ViewIdToTranslate(R.id.batteryRemainingIcon, END, filterShade),
+ ViewIdToTranslate(R.id.carrier_group, END, filterShade),
ViewIdToTranslate(R.id.clock, START, filterShade),
ViewIdToTranslate(R.id.date, START, filterShade)),
progressProvider = progressProvider)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 1259f5eed87a..6b2d7443392d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -23,6 +23,7 @@ import static android.view.View.VISIBLE;
import static androidx.constraintlayout.widget.ConstraintSet.END;
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION;
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
@@ -71,6 +72,7 @@ import android.os.VibrationEffect;
import android.provider.Settings;
import android.transition.ChangeBounds;
import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
import android.transition.TransitionManager;
import android.transition.TransitionSet;
import android.transition.TransitionValues;
@@ -98,6 +100,7 @@ import android.widget.FrameLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.SystemBarUtils;
@@ -116,6 +119,7 @@ import com.android.keyguard.dagger.KeyguardStatusViewComponent;
import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
import com.android.systemui.DejankUtils;
import com.android.systemui.Dumpable;
+import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.Interpolators;
@@ -159,14 +163,12 @@ import com.android.systemui.plugins.FalsingManager.FalsingTapListener;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.NotificationShelfController;
@@ -336,7 +338,7 @@ public final class NotificationPanelViewController implements Dumpable {
private final ScrimController mScrimController;
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private final TapAgainViewController mTapAgainViewController;
- private final LargeScreenShadeHeaderController mLargeScreenShadeHeaderController;
+ private final ShadeHeaderController mShadeHeaderController;
private final boolean mVibrateOnOpening;
private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
private final FlingAnimationUtils mFlingAnimationUtilsClosing;
@@ -353,6 +355,8 @@ public final class NotificationPanelViewController implements Dumpable {
private final NotificationGutsManager mGutsManager;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
private final QuickSettingsController mQsController;
+ private final InteractionJankMonitor mInteractionJankMonitor;
+ private final TouchHandler mTouchHandler = new TouchHandler();
private long mDownTime;
private boolean mTouchSlopExceededBeforeDown;
@@ -465,7 +469,7 @@ public final class NotificationPanelViewController implements Dumpable {
private int mPanelAlpha;
private Runnable mPanelAlphaEndAction;
private float mBottomAreaShadeAlpha;
- private final ValueAnimator mBottomAreaShadeAlphaAnimator;
+ final ValueAnimator mBottomAreaShadeAlphaAnimator;
private final AnimatableProperty mPanelAlphaAnimator = AnimatableProperty.from("panelAlpha",
NotificationPanelView::setPanelAlphaInternal,
NotificationPanelView::getCurrentPanelAlpha,
@@ -537,7 +541,7 @@ public final class NotificationPanelViewController implements Dumpable {
private final KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
private final KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
private float mMinExpandHeight;
- private ShadeHeightLogger mShadeHeightLogger;
+ private final ShadeHeightLogger mShadeHeightLogger;
private boolean mPanelUpdateWhenAnimatorEnds;
private boolean mHasVibratedOnOpen = false;
private int mFixedDuration = NO_FIXED_DURATION;
@@ -582,22 +586,21 @@ public final class NotificationPanelViewController implements Dumpable {
private boolean mGestureWaitForTouchSlop;
private boolean mIgnoreXTouchSlop;
private boolean mExpandLatencyTracking;
- private DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
- private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
- private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
- private GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
- private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
+ private final DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
+ private final OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
+ private final LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
+ private final GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
+ private final LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
- private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+ private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
private final KeyguardInteractor mKeyguardInteractor;
- private CoroutineDispatcher mMainDispatcher;
+ private final CoroutineDispatcher mMainDispatcher;
private boolean mIsOcclusionTransitionRunning = false;
private int mDreamingToLockscreenTransitionTranslationY;
private int mOccludedToLockscreenTransitionTranslationY;
private int mLockscreenToDreamingTransitionTranslationY;
private int mGoneToDreamingTransitionTranslationY;
private int mLockscreenToOccludedTransitionTranslationY;
- private boolean mUnocclusionTransitionFlagEnabled = false;
private final Runnable mFlingCollapseRunnable = () -> fling(0, false /* expand */,
mNextCollapseSpeedUpFactor, false /* expandBecauseOfFalsing */);
@@ -643,6 +646,19 @@ public final class NotificationPanelViewController implements Dumpable {
step.getTransitionState() == TransitionState.RUNNING;
};
+ private final TransitionListenerAdapter mKeyguardStatusAlignmentTransitionListener =
+ new TransitionListenerAdapter() {
+ @Override
+ public void onTransitionCancel(Transition transition) {
+ mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ mInteractionJankMonitor.end(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
+ }
+ };
+
@Inject
public NotificationPanelViewController(NotificationPanelView view,
@Main Handler handler,
@@ -692,12 +708,10 @@ public final class NotificationPanelViewController implements Dumpable {
QuickSettingsController quickSettingsController,
FragmentService fragmentService,
ContentResolver contentResolver,
- RecordingController recordingController,
- LargeScreenShadeHeaderController largeScreenShadeHeaderController,
+ ShadeHeaderController shadeHeaderController,
ScreenOffAnimationController screenOffAnimationController,
LockscreenGestureLogger lockscreenGestureLogger,
ShadeExpansionStateManager shadeExpansionStateManager,
- NotificationRemoteInputManager remoteInputManager,
Optional<SysUIUnfoldComponent> unfoldComponent,
SysUiState sysUiState,
Provider<KeyguardBottomAreaViewController> keyguardBottomAreaViewControllerProvider,
@@ -707,6 +721,7 @@ public final class NotificationPanelViewController implements Dumpable {
NotificationStackSizeCalculator notificationStackSizeCalculator,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
ShadeTransitionController shadeTransitionController,
+ InteractionJankMonitor interactionJankMonitor,
SystemClock systemClock,
KeyguardBottomAreaViewModel keyguardBottomAreaViewModel,
KeyguardBottomAreaInteractor keyguardBottomAreaInteractor,
@@ -721,6 +736,7 @@ public final class NotificationPanelViewController implements Dumpable {
DumpManager dumpManager,
KeyguardLongPressViewModel keyguardLongPressViewModel,
KeyguardInteractor keyguardInteractor) {
+ mInteractionJankMonitor = interactionJankMonitor;
keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@Override
public void onKeyguardFadingAwayChanged() {
@@ -753,7 +769,7 @@ public final class NotificationPanelViewController implements Dumpable {
});
mView.addOnLayoutChangeListener(new ShadeLayoutChangeListener());
- mView.setOnTouchListener(createTouchHandler());
+ mView.setOnTouchListener(getTouchHandler());
mView.setOnConfigurationChangedListener(config -> loadDimens());
mResources = mView.getResources();
@@ -813,7 +829,7 @@ public final class NotificationPanelViewController implements Dumpable {
mSplitShadeEnabled =
LargeScreenUtils.shouldUseSplitNotificationShade(mResources);
mView.setWillNotDraw(!DEBUG_DRAWABLE);
- mLargeScreenShadeHeaderController = largeScreenShadeHeaderController;
+ mShadeHeaderController = shadeHeaderController;
mLayoutInflater = layoutInflater;
mFeatureFlags = featureFlags;
mFalsingCollector = falsingCollector;
@@ -886,7 +902,6 @@ public final class NotificationPanelViewController implements Dumpable {
mNotificationPanelUnfoldAnimationController = unfoldComponent.map(
SysUIUnfoldComponent::getNotificationPanelUnfoldAnimationController);
- mUnocclusionTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
updateUserSwitcherFlags();
mKeyguardBottomAreaViewModel = keyguardBottomAreaViewModel;
mKeyguardBottomAreaInteractor = keyguardBottomAreaInteractor;
@@ -1040,67 +1055,55 @@ public final class NotificationPanelViewController implements Dumpable {
}
mTapAgainViewController.init();
- mLargeScreenShadeHeaderController.init();
+ mShadeHeaderController.init();
mKeyguardUnfoldTransition.ifPresent(u -> u.setup(mView));
mNotificationPanelUnfoldAnimationController.ifPresent(controller ->
controller.setup(mNotificationContainerParent));
- if (mUnocclusionTransitionFlagEnabled) {
- // Dreaming->Lockscreen
- collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(),
- mDreamingToLockscreenTransition, mMainDispatcher);
- collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(),
- setTransitionAlpha(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- collectFlow(mView, mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(
- mDreamingToLockscreenTransitionTranslationY),
- setTransitionY(mNotificationStackScrollLayoutController),
- mMainDispatcher);
-
- // Occluded->Lockscreen
- collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
- mOccludedToLockscreenTransition, mMainDispatcher);
- collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
- setTransitionAlpha(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- collectFlow(mView, mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(
- mOccludedToLockscreenTransitionTranslationY),
- setTransitionY(mNotificationStackScrollLayoutController),
- mMainDispatcher);
-
- // Lockscreen->Dreaming
- collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToDreamingTransition(),
- mLockscreenToDreamingTransition, mMainDispatcher);
- collectFlow(mView, mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha(),
- setTransitionAlpha(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- collectFlow(mView, mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(
- mLockscreenToDreamingTransitionTranslationY),
- setTransitionY(mNotificationStackScrollLayoutController),
- mMainDispatcher);
-
- // Gone->Dreaming
- collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(),
- mGoneToDreamingTransition, mMainDispatcher);
- collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
- setTransitionAlpha(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- collectFlow(mView, mGoneToDreamingTransitionViewModel.lockscreenTranslationY(
- mGoneToDreamingTransitionTranslationY),
- setTransitionY(mNotificationStackScrollLayoutController),
- mMainDispatcher);
-
- // Lockscreen->Occluded
- collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
- mLockscreenToOccludedTransition, mMainDispatcher);
- collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
- setTransitionAlpha(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- collectFlow(mView, mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(
- mLockscreenToOccludedTransitionTranslationY),
- setTransitionY(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- }
+ // Dreaming->Lockscreen
+ collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(),
+ mDreamingToLockscreenTransition, mMainDispatcher);
+ collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(),
+ setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ collectFlow(mView, mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(
+ mDreamingToLockscreenTransitionTranslationY),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+
+ // Occluded->Lockscreen
+ collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
+ mOccludedToLockscreenTransition, mMainDispatcher);
+ collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
+ setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ collectFlow(mView, mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(
+ mOccludedToLockscreenTransitionTranslationY),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+
+ // Lockscreen->Dreaming
+ collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToDreamingTransition(),
+ mLockscreenToDreamingTransition, mMainDispatcher);
+ collectFlow(mView, mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha(),
+ setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ collectFlow(mView, mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(
+ mLockscreenToDreamingTransitionTranslationY),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+
+ // Gone->Dreaming
+ collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(),
+ mGoneToDreamingTransition, mMainDispatcher);
+ collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
+ setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ collectFlow(mView, mGoneToDreamingTransitionViewModel.lockscreenTranslationY(
+ mGoneToDreamingTransitionTranslationY),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+
+ // Lockscreen->Occluded
+ collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
+ mLockscreenToOccludedTransition, mMainDispatcher);
+ collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
+ setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ collectFlow(mView, mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(
+ mLockscreenToOccludedTransitionTranslationY),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
}
@VisibleForTesting
@@ -1197,6 +1200,13 @@ public final class NotificationPanelViewController implements Dumpable {
}
private void onSplitShadeEnabledChanged() {
+ mShadeLog.logSplitShadeChanged(mSplitShadeEnabled);
+ // Reset any left over overscroll state. It is a rare corner case but can happen.
+ mQsController.setOverScrollAmount(0);
+ mScrimController.setNotificationsOverScrollAmount(0);
+ mNotificationStackScrollLayoutController.setOverExpansion(0);
+ mNotificationStackScrollLayoutController.setOverScrollAmount(0);
+
// when we switch between split shade and regular shade we want to enforce setting qs to
// the default state: expanded for split shade and collapsed otherwise
if (!isOnKeyguard() && mPanelExpanded) {
@@ -1553,6 +1563,7 @@ public final class NotificationPanelViewController implements Dumpable {
int statusConstraint = shouldBeCentered ? PARENT_ID : R.id.qs_edge_guideline;
constraintSet.connect(R.id.keyguard_status_view, END, statusConstraint, END);
if (animate) {
+ mInteractionJankMonitor.begin(mView, CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
ChangeBounds transition = new ChangeBounds();
if (mSplitShadeEnabled) {
// Excluding media from the transition on split-shade, as it doesn't transition
@@ -1576,6 +1587,7 @@ public final class NotificationPanelViewController implements Dumpable {
// The clock container can sometimes be null. If it is, just fall back to the
// old animation rather than setting up the custom animations.
if (clockContainerView == null || clockContainerView.getChildCount() == 0) {
+ transition.addListener(mKeyguardStatusAlignmentTransitionListener);
TransitionManager.beginDelayedTransition(
mNotificationContainerParent, transition);
} else {
@@ -1594,10 +1606,11 @@ public final class NotificationPanelViewController implements Dumpable {
adapter.setDuration(KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION);
adapter.addTarget(clockView);
set.addTransition(adapter);
-
+ set.addListener(mKeyguardStatusAlignmentTransitionListener);
TransitionManager.beginDelayedTransition(mNotificationContainerParent, set);
}
} else {
+ transition.addListener(mKeyguardStatusAlignmentTransitionListener);
TransitionManager.beginDelayedTransition(
mNotificationContainerParent, transition);
}
@@ -1634,10 +1647,6 @@ public final class NotificationPanelViewController implements Dumpable {
return mDozing && mDozeParameters.getAlwaysOn();
}
- boolean isDozing() {
- return mDozing;
- }
-
private boolean hasVisibleNotifications() {
return mNotificationStackScrollLayoutController
.getVisibleNotificationCount() != 0
@@ -1777,7 +1786,7 @@ public final class NotificationPanelViewController implements Dumpable {
if (animate && !isFullyCollapsed()) {
animateCloseQs(true);
} else {
- mQsController.closeQs();
+ closeQsIfPossible();
}
mNotificationStackScrollLayoutController.setOverScrollAmount(0f, true /* onTop */, animate,
!animate /* cancelAnimators */);
@@ -1914,7 +1923,6 @@ public final class NotificationPanelViewController implements Dumpable {
// we want to perform an overshoot animation when flinging open
final boolean addOverscroll =
expand
- && !mSplitShadeEnabled // Split shade has its own overscroll logic
&& mStatusBarStateController.getState() != KEYGUARD
&& mOverExpansion == 0.0f
&& vel >= 0;
@@ -2206,7 +2214,12 @@ public final class NotificationPanelViewController implements Dumpable {
&& mQsController.getFullyExpanded()) {
// Upon initialisation when we are not layouted yet we don't want to announce that we
// are fully expanded, hence the != 0.0f check.
- return mResources.getString(R.string.accessibility_desc_quick_settings);
+ if (mSplitShadeEnabled) {
+ // In split shade, QS is expanded but it also shows notifications
+ return mResources.getString(R.string.accessibility_desc_qs_notification_shade);
+ } else {
+ return mResources.getString(R.string.accessibility_desc_quick_settings);
+ }
} else if (mBarState == KEYGUARD) {
return mResources.getString(R.string.accessibility_desc_lock_screen);
} else {
@@ -2475,9 +2488,6 @@ public final class NotificationPanelViewController implements Dumpable {
}
private void onExpandingFinished() {
- if (!mUnocclusionTransitionFlagEnabled) {
- mScrimController.onExpandingFinished();
- }
mNotificationStackScrollLayoutController.onExpansionStopped();
mHeadsUpManager.onExpandingFinished();
mConversationNotificationManager.onNotificationPanelExpandStateChanged(isFullyCollapsed());
@@ -2585,9 +2595,14 @@ public final class NotificationPanelViewController implements Dumpable {
return;
}
mOverExpansion = overExpansion;
- // Translating the quick settings by half the overexpansion to center it in the background
- // frame
- mQsController.updateQsFrameTranslation();
+ if (mSplitShadeEnabled) {
+ mQsController.setOverScrollAmount((int) overExpansion);
+ mScrimController.setNotificationsOverScrollAmount((int) overExpansion);
+ } else {
+ // Translating the quick settings by half the overexpansion to center it in the
+ // background frame
+ mQsController.updateQsFrameTranslation();
+ }
mNotificationStackScrollLayoutController.setOverExpansion(overExpansion);
}
@@ -2868,7 +2883,10 @@ public final class NotificationPanelViewController implements Dumpable {
mHeadsUpStartHeight = startHeight;
float scrimMinFraction;
if (mSplitShadeEnabled) {
- boolean highHun = mHeadsUpStartHeight * 2.5 > mSplitShadeScrimTransitionDistance;
+ boolean highHun = mHeadsUpStartHeight * 2.5
+ >
+ (mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)
+ ? mSplitShadeFullTransitionDistance : mSplitShadeScrimTransitionDistance);
// if HUN height is higher than 40% of predefined transition distance, it means HUN
// is too high for regular transition. In that case we need to calculate transition
// distance - here we take scrim transition distance as equal to shade transition
@@ -3318,8 +3336,8 @@ public final class NotificationPanelViewController implements Dumpable {
}
@VisibleForTesting
- TouchHandler createTouchHandler() {
- return new TouchHandler();
+ TouchHandler getTouchHandler() {
+ return mTouchHandler;
}
public NotificationStackScrollLayoutController getNotificationStackScrollLayoutController() {
@@ -3327,7 +3345,7 @@ public final class NotificationPanelViewController implements Dumpable {
}
public void disable(int state1, int state2, boolean animated) {
- mLargeScreenShadeHeaderController.disable(state1, state2, animated);
+ mShadeHeaderController.disable(state1, state2, animated);
}
/**
@@ -3589,7 +3607,7 @@ public final class NotificationPanelViewController implements Dumpable {
private void fling(float vel, boolean expand, float collapseSpeedUpFactor,
boolean expandBecauseOfFalsing) {
- float target = expand ? getMaxPanelHeight() : 0;
+ float target = expand ? getMaxPanelTransitionDistance() : 0;
if (!expand) {
setClosing(true);
}
@@ -3674,7 +3692,7 @@ public final class NotificationPanelViewController implements Dumpable {
float maxPanelHeight = getMaxPanelTransitionDistance();
if (mHeightAnimator == null) {
// Split shade has its own overscroll logic
- if (mTracking && !mSplitShadeEnabled) {
+ if (mTracking) {
float overExpansionPixels = Math.max(0, h - maxPanelHeight);
setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */);
}
@@ -3967,14 +3985,14 @@ public final class NotificationPanelViewController implements Dumpable {
return mView.post(action);
}
- /** */
- public boolean sendInterceptTouchEventToView(MotionEvent event) {
- return mView.onInterceptTouchEvent(event);
+ /** Sends an external (e.g. Status Bar) intercept touch event to the Shade touch handler. */
+ public boolean handleExternalInterceptTouch(MotionEvent event) {
+ return mTouchHandler.onInterceptTouchEvent(event);
}
- /** */
- public boolean sendTouchEventToView(MotionEvent event) {
- return mView.dispatchTouchEvent(event);
+ /** Sends an external (e.g. Status Bar) touch event to the Shade touch handler. */
+ public boolean handleExternalTouch(MotionEvent event) {
+ return mTouchHandler.onTouchEvent(event);
}
/** */
@@ -3992,14 +4010,6 @@ public final class NotificationPanelViewController implements Dumpable {
return mView.isEnabled();
}
- int getDisplayRightInset() {
- return mDisplayRightInset;
- }
-
- int getDisplayLeftInset() {
- return mDisplayLeftInset;
- }
-
float getOverStretchAmount() {
return mOverStretchAmount;
}
@@ -4008,10 +4018,6 @@ public final class NotificationPanelViewController implements Dumpable {
return mMinFraction;
}
- boolean getCollapsedOnDown() {
- return mCollapsedOnDown;
- }
-
int getNavigationBarBottomHeight() {
return mNavigationBarBottomHeight;
}
@@ -4020,9 +4026,17 @@ public final class NotificationPanelViewController implements Dumpable {
return mExpandingFromHeadsUp;
}
- /** TODO: remove need for this delegate (b/254870148) */
- public void closeQs() {
- mQsController.closeQs();
+ /**
+ * We don't always want to close QS when requested as shade might be in a different state
+ * already e.g. when going from collapse to expand very quickly. In that case StatusBar
+ * window might send signal to collapse QS but we might be already expanding and in split
+ * shade QS are always expanded
+ */
+ private void closeQsIfPossible() {
+ boolean openOrOpening = isShadeFullyOpen() || isExpanding();
+ if (!(mSplitShadeEnabled && openOrOpening)) {
+ mQsController.closeQs();
+ }
}
/** TODO: remove need for this delegate (b/254870148) */
@@ -4567,7 +4581,7 @@ public final class NotificationPanelViewController implements Dumpable {
}
/** Handles MotionEvents for the Shade. */
- public final class TouchHandler implements View.OnTouchListener {
+ public final class TouchHandler implements View.OnTouchListener, Gefingerpoken {
private long mLastTouchDownTime = -1L;
/** @see ViewGroup#onInterceptTouchEvent(MotionEvent) */
@@ -4713,6 +4727,11 @@ public final class NotificationPanelViewController implements Dumpable {
@Override
public boolean onTouch(View v, MotionEvent event) {
+ return onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (event.getDownTime() == mLastTouchDownTime) {
// An issue can occur when swiping down after unlock, where multiple down
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
index 1f0cbf9af51c..74a61a3efebe 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
@@ -16,7 +16,7 @@
package com.android.systemui.shade;
-import static android.os.Trace.TRACE_TAG_ALWAYS;
+import static android.os.Trace.TRACE_TAG_APP;
import static android.view.WindowInsets.Type.systemBars;
import static com.android.systemui.statusbar.phone.CentralSurfaces.DEBUG;
@@ -328,7 +328,7 @@ public class NotificationShadeWindowView extends FrameLayout {
@Override
public void requestLayout() {
- Trace.instant(TRACE_TAG_ALWAYS, "NotificationShadeWindowView#requestLayout");
+ Trace.instant(TRACE_TAG_APP, "NotificationShadeWindowView#requestLayout");
super.requestLayout();
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 60fa865b83bc..13f7be6b0e6a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -38,8 +38,6 @@ import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dock.DockManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -47,6 +45,7 @@ import com.android.systemui.keyguard.shared.model.TransitionState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationInsetsController;
@@ -132,11 +131,11 @@ public class NotificationShadeWindowViewController {
NotificationInsetsController notificationInsetsController,
AmbientState ambientState,
PulsingGestureListener pulsingGestureListener,
- FeatureFlags featureFlags,
KeyguardBouncerViewModel keyguardBouncerViewModel,
KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory,
AlternateBouncerInteractor alternateBouncerInteractor,
- KeyguardTransitionInteractor keyguardTransitionInteractor
+ KeyguardTransitionInteractor keyguardTransitionInteractor,
+ PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel
) {
mLockscreenShadeTransitionController = transitionController;
mFalsingCollector = falsingCollector;
@@ -163,12 +162,11 @@ public class NotificationShadeWindowViewController {
KeyguardBouncerViewBinder.bind(
mView.findViewById(R.id.keyguard_bouncer_container),
keyguardBouncerViewModel,
+ primaryBouncerToGoneTransitionViewModel,
keyguardBouncerComponentFactory);
- if (featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION)) {
- collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
- mLockscreenToDreamingTransition);
- }
+ collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
+ mLockscreenToDreamingTransition);
}
/**
@@ -242,7 +240,9 @@ public class NotificationShadeWindowViewController {
mFalsingCollector.onTouchEvent(ev);
mPulsingWakeupGestureHandler.onTouchEvent(ev);
- mStatusBarKeyguardViewManager.onTouch(ev);
+ if (mStatusBarKeyguardViewManager.onTouch(ev)) {
+ return true;
+ }
if (mBrightnessMirror != null
&& mBrightnessMirror.getVisibility() == View.VISIBLE) {
// Disallow new pointers while the brightness mirror is visible. This is so that
@@ -344,7 +344,7 @@ public class NotificationShadeWindowViewController {
MotionEvent cancellation = MotionEvent.obtain(ev);
cancellation.setAction(MotionEvent.ACTION_CANCEL);
mStackScrollLayout.onInterceptTouchEvent(cancellation);
- mNotificationPanelViewController.sendInterceptTouchEventToView(cancellation);
+ mNotificationPanelViewController.handleExternalInterceptTouch(cancellation);
cancellation.recycle();
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
index de02115184b6..fb7c5c2e31fa 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
@@ -29,8 +29,6 @@ import androidx.constraintlayout.widget.ConstraintSet.START
import androidx.constraintlayout.widget.ConstraintSet.TOP
import com.android.systemui.R
import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.fragments.FragmentService
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.plugins.qs.QS
@@ -49,14 +47,13 @@ import kotlin.reflect.KMutableProperty0
internal const val INSET_DEBOUNCE_MILLIS = 500L
class NotificationsQSContainerController @Inject constructor(
- view: NotificationsQuickSettingsContainer,
- private val navigationModeController: NavigationModeController,
- private val overviewProxyService: OverviewProxyService,
- private val largeScreenShadeHeaderController: LargeScreenShadeHeaderController,
- private val shadeExpansionStateManager: ShadeExpansionStateManager,
- private val featureFlags: FeatureFlags,
- private val fragmentService: FragmentService,
- @Main private val delayableExecutor: DelayableExecutor
+ view: NotificationsQuickSettingsContainer,
+ private val navigationModeController: NavigationModeController,
+ private val overviewProxyService: OverviewProxyService,
+ private val shadeHeaderController: ShadeHeaderController,
+ private val shadeExpansionStateManager: ShadeExpansionStateManager,
+ private val fragmentService: FragmentService,
+ @Main private val delayableExecutor: DelayableExecutor
) : ViewController<NotificationsQuickSettingsContainer>(view), QSContainerController {
private var qsExpanded = false
@@ -75,8 +72,6 @@ class NotificationsQSContainerController @Inject constructor(
private var panelMarginHorizontal = 0
private var topMargin = 0
- private val useCombinedQSHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)
-
private var isGestureNavigation = true
private var taskbarVisible = false
private val taskbarVisibilityListener: OverviewProxyListener = object : OverviewProxyListener {
@@ -184,7 +179,7 @@ class NotificationsQSContainerController @Inject constructor(
override fun setCustomizerShowing(showing: Boolean, animationDuration: Long) {
if (showing != isQSCustomizing) {
isQSCustomizing = showing
- largeScreenShadeHeaderController.startCustomizingAnimation(showing, animationDuration)
+ shadeHeaderController.startCustomizingAnimation(showing, animationDuration)
updateBottomSpacing()
}
}
@@ -250,9 +245,7 @@ class NotificationsQSContainerController @Inject constructor(
if (largeScreenShadeHeaderActive) {
constraintSet.constrainHeight(R.id.split_shade_status_bar, largeScreenShadeHeaderHeight)
} else {
- if (useCombinedQSHeaders) {
- constraintSet.constrainHeight(R.id.split_shade_status_bar, WRAP_CONTENT)
- }
+ constraintSet.constrainHeight(R.id.split_shade_status_bar, WRAP_CONTENT)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index c0ef4c1a872a..50e6c719e646 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -56,7 +56,6 @@ import com.android.systemui.animation.Interpolators;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.media.controls.pipeline.MediaDataManager;
import com.android.systemui.media.controls.ui.MediaHierarchyManager;
@@ -110,7 +109,7 @@ public class QuickSettingsController {
private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private final NotificationShadeDepthController mDepthController;
- private final LargeScreenShadeHeaderController mLargeScreenShadeHeaderController;
+ private final ShadeHeaderController mShadeHeaderController;
private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
private final KeyguardStateController mKeyguardStateController;
private final KeyguardBypassController mKeyguardBypassController;
@@ -194,7 +193,12 @@ public class QuickSettingsController {
private boolean mAnimatingHiddenFromCollapsed;
private boolean mVisible;
private float mExpansionHeight;
+ /**
+ * QS height when QS expansion fraction is 0 so when QS is collapsed. That state doesn't really
+ * exist for split shade so currently this value is always 0 then.
+ */
private int mMinExpansionHeight;
+ /** QS height when QS expansion fraction is 1 so qs is fully expanded */
private int mMaxExpansionHeight;
/** Expansion fraction of the notification shade */
private float mShadeExpandedFraction;
@@ -276,7 +280,7 @@ public class QuickSettingsController {
NotificationStackScrollLayoutController notificationStackScrollLayoutController,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
NotificationShadeDepthController notificationShadeDepthController,
- LargeScreenShadeHeaderController largeScreenShadeHeaderController,
+ ShadeHeaderController shadeHeaderController,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
KeyguardStateController keyguardStateController,
KeyguardBypassController keyguardBypassController,
@@ -315,7 +319,7 @@ public class QuickSettingsController {
mNotificationStackScrollLayoutController = notificationStackScrollLayoutController;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mDepthController = notificationShadeDepthController;
- mLargeScreenShadeHeaderController = largeScreenShadeHeaderController;
+ mShadeHeaderController = shadeHeaderController;
mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
mKeyguardStateController = keyguardStateController;
mKeyguardBypassController = keyguardBypassController;
@@ -396,18 +400,10 @@ public class QuickSettingsController {
mResources.getDimensionPixelSize(R.dimen.large_screen_shade_header_height);
int topMargin = mUseLargeScreenShadeHeader ? mLargeScreenShadeHeaderHeight :
mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_top);
- mLargeScreenShadeHeaderController.setLargeScreenActive(mUseLargeScreenShadeHeader);
+ mShadeHeaderController.setLargeScreenActive(mUseLargeScreenShadeHeader);
mAmbientState.setStackTopMargin(topMargin);
- // TODO: When the flag is eventually removed, it means that we have a single view that is
- // the same height in QQS and in Large Screen (large_screen_shade_header_height). Eventually
- // the concept of largeScreenHeader or quickQsHeader will disappear outside of the class
- // that controls the view as the offset needs to be the same regardless.
- if (mUseLargeScreenShadeHeader || mFeatureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)) {
- mQuickQsHeaderHeight = mLargeScreenShadeHeaderHeight;
- } else {
- mQuickQsHeaderHeight = SystemBarUtils.getQuickQsOffsetHeight(mPanelView.getContext());
- }
+ mQuickQsHeaderHeight = mLargeScreenShadeHeaderHeight;
mEnableClipping = mResources.getBoolean(R.bool.qs_enable_clipping);
}
@@ -434,6 +430,11 @@ public class QuickSettingsController {
updateExpansionEnabledAmbient();
}
+ @VisibleForTesting
+ void setStatusBarMinHeight(int height) {
+ mStatusBarMinHeight = height;
+ }
+
int getHeaderHeight() {
return mQs.getHeader().getHeight();
}
@@ -483,7 +484,8 @@ public class QuickSettingsController {
}
/** Returns whether or not event should open QS */
- private boolean isOpenQsEvent(MotionEvent event) {
+ @VisibleForTesting
+ boolean isOpenQsEvent(MotionEvent event) {
final int pointerCount = event.getPointerCount();
final int action = event.getActionMasked();
@@ -663,8 +665,15 @@ public class QuickSettingsController {
mDozing = dozing;
}
- /** set QS state to closed */
+ /**
+ * This method closes QS but in split shade it should be used only in special cases: to make
+ * sure QS closes when shade is closed as well. Otherwise it will result in QS disappearing
+ * from split shade
+ */
public void closeQs() {
+ if (mSplitShadeEnabled) {
+ mShadeLog.d("Closing QS while in split shade");
+ }
cancelExpansionAnimation();
setExpansionHeight(getMinExpansionHeight());
// qsExpandImmediate is a safety latch in case we're calling closeQS while we're in the
@@ -693,6 +702,7 @@ public class QuickSettingsController {
/** update Qs height state */
public void setExpansionHeight(float height) {
+ checkCorrectSplitShadeState(height);
int maxHeight = getMaxExpansionHeight();
height = Math.min(Math.max(
height, getMinExpansionHeight()), maxHeight);
@@ -714,6 +724,14 @@ public class QuickSettingsController {
}
}
+ /** TODO(b/269742565) Remove this logging */
+ private void checkCorrectSplitShadeState(float height) {
+ if (mSplitShadeEnabled && height == 0
+ && mPanelViewControllerLazy.get().isShadeFullyOpen()) {
+ Log.wtfStack(TAG, "qsExpansion set to 0 while split shade is expanding or open");
+ }
+ }
+
/** */
public void setHeightOverrideToDesiredHeight() {
if (isSizeChangeAnimationRunning() && isQsFragmentCreated()) {
@@ -803,6 +821,10 @@ public class QuickSettingsController {
}
}
+ void setOverScrollAmount(int overExpansion) {
+ mQs.setOverScrollAmount(overExpansion);
+ }
+
private void setOverScrolling(boolean overscrolling) {
mStackScrollerOverscrolling = overscrolling;
if (mQs != null) {
@@ -835,6 +857,7 @@ public class QuickSettingsController {
@VisibleForTesting
void setExpandImmediate(boolean expandImmediate) {
if (expandImmediate != mExpandImmediate) {
+ mShadeLog.logQsExpandImmediateChanged(expandImmediate);
mExpandImmediate = expandImmediate;
mShadeExpansionStateManager.notifyExpandImmediateChange(expandImmediate);
}
@@ -844,6 +867,11 @@ public class QuickSettingsController {
mTwoFingerExpandPossible = expandPossible;
}
+ @VisibleForTesting
+ boolean isTwoFingerExpandPossible() {
+ return mTwoFingerExpandPossible;
+ }
+
/** Called when Qs starts expanding */
private void onExpansionStarted() {
cancelExpansionAnimation();
@@ -919,9 +947,9 @@ public class QuickSettingsController {
float shadeExpandedFraction = mBarState == KEYGUARD
? mPanelViewControllerLazy.get().getLockscreenShadeDragProgress()
: mShadeExpandedFraction;
- mLargeScreenShadeHeaderController.setShadeExpandedFraction(shadeExpandedFraction);
- mLargeScreenShadeHeaderController.setQsExpandedFraction(qsExpansionFraction);
- mLargeScreenShadeHeaderController.setQsVisible(mVisible);
+ mShadeHeaderController.setShadeExpandedFraction(shadeExpandedFraction);
+ mShadeHeaderController.setQsExpandedFraction(qsExpansionFraction);
+ mShadeHeaderController.setQsVisible(mVisible);
}
/** */
@@ -1007,7 +1035,11 @@ public class QuickSettingsController {
private void setClippingBounds() {
float qsExpansionFraction = computeExpansionFraction();
final int qsPanelBottomY = calculateBottomPosition(qsExpansionFraction);
- final boolean qsVisible = (qsExpansionFraction > 0 || qsPanelBottomY > 0);
+ // Split shade has no QQS
+ final boolean qqsVisible =
+ !mSplitShadeEnabled && qsExpansionFraction == 0 && qsPanelBottomY > 0;
+ final boolean qsVisible = qsExpansionFraction > 0;
+ final boolean qsOrQqsVisible = qqsVisible || qsVisible;
checkCorrectScrimVisibility(qsExpansionFraction);
int top = calculateTopClippingBound(qsPanelBottomY);
@@ -1016,7 +1048,7 @@ public class QuickSettingsController {
int right = calculateRightClippingBound();
// top should never be lower than bottom, otherwise it will be invisible.
top = Math.min(top, bottom);
- applyClippingBounds(left, top, right, bottom, qsVisible);
+ applyClippingBounds(left, top, right, bottom, qsOrQqsVisible);
}
/**
@@ -1360,7 +1392,8 @@ public class QuickSettingsController {
return mTouchAboveFalsingThreshold;
}
- private void onHeightChanged() {
+ @VisibleForTesting
+ void onHeightChanged() {
mMaxExpansionHeight = isQsFragmentCreated() ? mQs.getDesiredHeight() : 0;
if (mExpanded && mFullyExpanded) {
mExpansionHeight = mMaxExpansionHeight;
@@ -1377,6 +1410,9 @@ public class QuickSettingsController {
}
private void collapseOrExpandQs() {
+ if (mSplitShadeEnabled) {
+ return; // QS is always expanded in split shade
+ }
onExpansionStarted();
if (getExpanded()) {
flingQs(0, FLING_COLLAPSE, null, true);
@@ -1387,7 +1423,7 @@ public class QuickSettingsController {
}
private void onScroll(int scrollY) {
- mLargeScreenShadeHeaderController.setQsScrollY(scrollY);
+ mShadeHeaderController.setQsScrollY(scrollY);
if (scrollY > 0 && !mFullyExpanded) {
// TODO (b/265193930): remove dependency on NPVC
// If we are scrolling QS, we should be fully expanded.
@@ -1662,7 +1698,8 @@ public class QuickSettingsController {
return false;
}
- private void onPanelExpansionChanged(ShadeExpansionChangeEvent event) {
+ @VisibleForTesting
+ void onPanelExpansionChanged(ShadeExpansionChangeEvent event) {
mShadeExpandedFraction = event.getFraction();
}
@@ -1706,12 +1743,16 @@ public class QuickSettingsController {
*/
private void flingQs(float vel, int type, final Runnable onFinishRunnable,
boolean isClick) {
+ mShadeLog.flingQs(type, isClick);
float target;
switch (type) {
case FLING_EXPAND:
target = getMaxExpansionHeight();
break;
case FLING_COLLAPSE:
+ if (mSplitShadeEnabled) { // TODO:(b/269742565) remove below log
+ Log.wtfStack(TAG, "FLING_COLLAPSE called in split shade");
+ }
target = getMinExpansionHeight();
break;
case FLING_HIDE:
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
index 026673adb86b..c1369935db54 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
@@ -270,8 +270,6 @@ public final class ShadeControllerImpl implements ShadeController {
// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
mNotificationPanelViewController.collapsePanel(false, false, 1.0f);
- mNotificationPanelViewController.closeQs();
-
mExpandedVisible = false;
notifyVisibilityChanged(false);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
index a1767cc5888d..f4b1cc5f71be 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
@@ -107,7 +107,7 @@ class ShadeExpansionStateManager @Inject constructor() : ShadeStateEvents {
*
* @param fraction the fraction from the expansion in [0, 1]
* @param expanded whether the panel is currently expanded; this is independent from the
- * fraction as the panel also might be expanded if the fraction is 0.
+ * fraction as the panel also might be expanded if the fraction is 0.
* @param tracking whether we're currently tracking the user's gesture.
*/
fun onPanelExpansionChanged(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index 9d8ed460dece..b79f32a6eae1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -41,22 +41,21 @@ import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.qs.ChipVisibilityListener
import com.android.systemui.qs.HeaderPrivacyIconsController
import com.android.systemui.qs.carrier.QSCarrierGroup
import com.android.systemui.qs.carrier.QSCarrierGroupController
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.HEADER_TRANSITION_ID
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.QS_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.HEADER_TRANSITION_ID
+import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_HEADER_TRANSITION_ID
+import com.android.systemui.shade.ShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.QS_HEADER_CONSTRAINT
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.StatusIconContainer
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
-import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.LARGE_SCREEN_BATTERY_CONTROLLER
-import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.LARGE_SCREEN_SHADE_HEADER
+import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SHADE_HEADER
import com.android.systemui.statusbar.policy.Clock
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.VariableDateView
@@ -67,30 +66,27 @@ import javax.inject.Inject
import javax.inject.Named
/**
- * Controller for QS header on Large Screen width (large screen + landscape).
+ * Controller for QS header.
*
- * Additionally, this serves as the staging ground for the combined QS headers. A single
- * [MotionLayout] that changes constraints depending on the configuration and can animate the
- * expansion of the headers in small screen portrait.
- *
- * [header] will be a [MotionLayout] if [Flags.COMBINED_QS_HEADERS] is enabled. In this case, the
- * [MotionLayout] has one transitions:
+ * [header] is a [MotionLayout] that has two transitions:
* * [HEADER_TRANSITION_ID]: [QQS_HEADER_CONSTRAINT] <-> [QS_HEADER_CONSTRAINT] for portrait
* handheld device configuration.
+ * * [LARGE_SCREEN_HEADER_TRANSITION_ID]: [LARGE_SCREEN_HEADER_CONSTRAINT] for all other
+ * configurations
*/
@CentralSurfacesScope
-class LargeScreenShadeHeaderController @Inject constructor(
- @Named(LARGE_SCREEN_SHADE_HEADER) private val header: View,
+class ShadeHeaderController
+@Inject
+constructor(
+ @Named(SHADE_HEADER) private val header: MotionLayout,
private val statusBarIconController: StatusBarIconController,
private val tintedIconManagerFactory: StatusBarIconController.TintedIconManager.Factory,
private val privacyIconsController: HeaderPrivacyIconsController,
private val insetsProvider: StatusBarContentInsetsProvider,
private val configurationController: ConfigurationController,
private val variableDateViewControllerFactory: VariableDateViewController.Factory,
- @Named(LARGE_SCREEN_BATTERY_CONTROLLER)
- private val batteryMeterViewController: BatteryMeterViewController,
+ @Named(SHADE_HEADER) private val batteryMeterViewController: BatteryMeterViewController,
private val dumpManager: DumpManager,
- private val featureFlags: FeatureFlags,
private val qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder,
private val combinedShadeHeadersConstraintManager: CombinedShadeHeadersConstraintManager,
private val demoModeController: DemoModeController,
@@ -98,30 +94,24 @@ class LargeScreenShadeHeaderController @Inject constructor(
) : ViewController<View>(header), Dumpable {
companion object {
- /** IDs for transitions and constraints for the [MotionLayout]. These are only used when
- * [Flags.COMBINED_QS_HEADERS] is enabled.
- */
- @VisibleForTesting
- internal val HEADER_TRANSITION_ID = R.id.header_transition
+ /** IDs for transitions and constraints for the [MotionLayout]. */
+ @VisibleForTesting internal val HEADER_TRANSITION_ID = R.id.header_transition
@VisibleForTesting
internal val LARGE_SCREEN_HEADER_TRANSITION_ID = R.id.large_screen_header_transition
- @VisibleForTesting
- internal val QQS_HEADER_CONSTRAINT = R.id.qqs_header_constraint
- @VisibleForTesting
- internal val QS_HEADER_CONSTRAINT = R.id.qs_header_constraint
+ @VisibleForTesting internal val QQS_HEADER_CONSTRAINT = R.id.qqs_header_constraint
+ @VisibleForTesting internal val QS_HEADER_CONSTRAINT = R.id.qs_header_constraint
@VisibleForTesting
internal val LARGE_SCREEN_HEADER_CONSTRAINT = R.id.large_screen_header_constraint
- private fun Int.stateToString() = when (this) {
- QQS_HEADER_CONSTRAINT -> "QQS Header"
- QS_HEADER_CONSTRAINT -> "QS Header"
- LARGE_SCREEN_HEADER_CONSTRAINT -> "Large Screen Header"
- else -> "Unknown state $this"
- }
+ private fun Int.stateToString() =
+ when (this) {
+ QQS_HEADER_CONSTRAINT -> "QQS Header"
+ QS_HEADER_CONSTRAINT -> "QS Header"
+ LARGE_SCREEN_HEADER_CONSTRAINT -> "Large Screen Header"
+ else -> "Unknown state $this"
+ }
}
- private val combinedHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)
-
private lateinit var iconManager: StatusBarIconController.TintedIconManager
private lateinit var carrierIconSlots: List<String>
private lateinit var qsCarrierGroupController: QSCarrierGroupController
@@ -180,9 +170,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
onHeaderStateChanged()
}
- /**
- * Expansion fraction of the QQS/QS shade. This is not the expansion between QQS <-> QS.
- */
+ /** Expansion fraction of the QQS/QS shade. This is not the expansion between QQS <-> QS. */
var shadeExpandedFraction = -1f
set(value) {
if (qsVisible && field != value) {
@@ -191,9 +179,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
}
- /**
- * Expansion fraction of the QQS <-> QS animation.
- */
+ /** Expansion fraction of the QQS <-> QS animation. */
var qsExpandedFraction = -1f
set(value) {
if (visible && field != value) {
@@ -202,9 +188,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
}
- /**
- * Current scroll of QS.
- */
+ /** Current scroll of QS. */
var qsScrollY = 0
set(value) {
if (field != value) {
@@ -213,40 +197,41 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
}
- private val insetListener = View.OnApplyWindowInsetsListener { view, insets ->
- updateConstraintsForInsets(view as MotionLayout, insets)
- lastInsets = WindowInsets(insets)
+ private val insetListener =
+ View.OnApplyWindowInsetsListener { view, insets ->
+ updateConstraintsForInsets(view as MotionLayout, insets)
+ lastInsets = WindowInsets(insets)
- view.onApplyWindowInsets(insets)
- }
+ view.onApplyWindowInsets(insets)
+ }
- private val demoModeReceiver = object : DemoMode {
- override fun demoCommands() = listOf(DemoMode.COMMAND_CLOCK)
- override fun dispatchDemoCommand(command: String, args: Bundle) =
- clock.dispatchDemoCommand(command, args)
- override fun onDemoModeStarted() = clock.onDemoModeStarted()
- override fun onDemoModeFinished() = clock.onDemoModeFinished()
- }
+ private val demoModeReceiver =
+ object : DemoMode {
+ override fun demoCommands() = listOf(DemoMode.COMMAND_CLOCK)
+ override fun dispatchDemoCommand(command: String, args: Bundle) =
+ clock.dispatchDemoCommand(command, args)
+ override fun onDemoModeStarted() = clock.onDemoModeStarted()
+ override fun onDemoModeFinished() = clock.onDemoModeFinished()
+ }
- private val chipVisibilityListener: ChipVisibilityListener = object : ChipVisibilityListener {
- override fun onChipVisibilityRefreshed(visible: Boolean) {
- if (header is MotionLayout) {
+ private val chipVisibilityListener: ChipVisibilityListener =
+ object : ChipVisibilityListener {
+ override fun onChipVisibilityRefreshed(visible: Boolean) {
// If the privacy chip is visible, we hide the status icons and battery remaining
// icon, only in QQS.
- val update = combinedShadeHeadersConstraintManager
- .privacyChipVisibilityConstraints(visible)
+ val update =
+ combinedShadeHeadersConstraintManager.privacyChipVisibilityConstraints(visible)
header.updateAllConstraints(update)
}
}
- }
private val configurationControllerListener =
object : ConfigurationController.ConfigurationListener {
- override fun onConfigChanged(newConfig: Configuration?) {
- if (header !is MotionLayout) {
- val left = header.resources.getDimensionPixelSize(
- R.dimen.large_screen_shade_header_left_padding
- )
+ override fun onConfigChanged(newConfig: Configuration?) {
+ val left =
+ header.resources.getDimensionPixelSize(
+ R.dimen.large_screen_shade_header_left_padding
+ )
header.setPadding(
left,
header.paddingTop,
@@ -254,26 +239,21 @@ class LargeScreenShadeHeaderController @Inject constructor(
header.paddingBottom
)
}
- }
- override fun onDensityOrFontScaleChanged() {
- clock.setTextAppearance(R.style.TextAppearance_QS_Status)
- date.setTextAppearance(R.style.TextAppearance_QS_Status)
- qsCarrierGroup.updateTextAppearance(R.style.TextAppearance_QS_Status_Carriers)
- if (header is MotionLayout) {
+ override fun onDensityOrFontScaleChanged() {
+ clock.setTextAppearance(R.style.TextAppearance_QS_Status)
+ date.setTextAppearance(R.style.TextAppearance_QS_Status)
+ qsCarrierGroup.updateTextAppearance(R.style.TextAppearance_QS_Status_Carriers)
loadConstraints()
- header.minHeight = resources
- .getDimensionPixelSize(R.dimen.large_screen_shade_header_min_height)
+ header.minHeight =
+ resources.getDimensionPixelSize(R.dimen.large_screen_shade_header_min_height)
lastInsets?.let { updateConstraintsForInsets(header, it) }
+ updateResources()
}
- updateResources()
}
- }
override fun onInit() {
- if (header is MotionLayout) {
- variableDateViewControllerFactory.create(date as VariableDateView).init()
- }
+ variableDateViewControllerFactory.create(date as VariableDateView).init()
batteryMeterViewController.init()
// battery settings same as in QS icons
@@ -286,20 +266,10 @@ class LargeScreenShadeHeaderController @Inject constructor(
carrierIconSlots =
listOf(header.context.getString(com.android.internal.R.string.status_bar_mobile))
- qsCarrierGroupController = qsCarrierGroupControllerBuilder
- .setQSCarrierGroup(qsCarrierGroup)
- .build()
-
- if (!combinedHeaders) {
- // In the new header, we display alarm icon but we ignore it when not using the new
- // headers.
- iconContainer.addIgnoredSlot(
- context.getString(com.android.internal.R.string.status_bar_alarm_clock)
- )
- }
- if (combinedHeaders) {
- privacyIconsController.onParentVisible()
- }
+ qsCarrierGroupController =
+ qsCarrierGroupControllerBuilder.setQSCarrierGroup(qsCarrierGroup).build()
+
+ privacyIconsController.onParentVisible()
}
override fun onViewAttached() {
@@ -307,16 +277,14 @@ class LargeScreenShadeHeaderController @Inject constructor(
updateVisibility()
updateTransition()
- if (header is MotionLayout) {
- header.setOnApplyWindowInsetsListener(insetListener)
+ header.setOnApplyWindowInsetsListener(insetListener)
- clock.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
- val newPivot = if (v.isLayoutRtl) v.width.toFloat() else 0f
- v.pivotX = newPivot
- v.pivotY = v.height.toFloat() / 2
+ clock.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
+ val newPivot = if (v.isLayoutRtl) v.width.toFloat() else 0f
+ v.pivotX = newPivot
+ v.pivotY = v.height.toFloat() / 2
- qsCarrierGroup.setPaddingRelative((v.width * v.scaleX).toInt(), 0, 0, 0)
- }
+ qsCarrierGroup.setPaddingRelative((v.width * v.scaleX).toInt(), 0, 0, 0)
}
dumpManager.registerDumpable(this)
@@ -341,30 +309,30 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
fun startCustomizingAnimation(show: Boolean, duration: Long) {
- header.animate()
- .setDuration(duration)
- .alpha(if (show) 0f else 1f)
- .setInterpolator(if (show) Interpolators.ALPHA_OUT else Interpolators.ALPHA_IN)
- .setListener(CustomizerAnimationListener(show))
- .start()
+ header
+ .animate()
+ .setDuration(duration)
+ .alpha(if (show) 0f else 1f)
+ .setInterpolator(if (show) Interpolators.ALPHA_OUT else Interpolators.ALPHA_IN)
+ .setListener(CustomizerAnimationListener(show))
+ .start()
}
private fun loadConstraints() {
- if (header is MotionLayout) {
- // Use resources.getXml instead of passing the resource id due to bug b/205018300
- header.getConstraintSet(QQS_HEADER_CONSTRAINT)
- .load(context, resources.getXml(R.xml.qqs_header))
- header.getConstraintSet(QS_HEADER_CONSTRAINT)
- .load(context, resources.getXml(R.xml.qs_header))
- header.getConstraintSet(LARGE_SCREEN_HEADER_CONSTRAINT)
- .load(context, resources.getXml(R.xml.large_screen_shade_header))
- }
+ // Use resources.getXml instead of passing the resource id due to bug b/205018300
+ header
+ .getConstraintSet(QQS_HEADER_CONSTRAINT)
+ .load(context, resources.getXml(R.xml.qqs_header))
+ header
+ .getConstraintSet(QS_HEADER_CONSTRAINT)
+ .load(context, resources.getXml(R.xml.qs_header))
+ header
+ .getConstraintSet(LARGE_SCREEN_HEADER_CONSTRAINT)
+ .load(context, resources.getXml(R.xml.large_screen_shade_header))
}
private fun updateConstraintsForInsets(view: MotionLayout, insets: WindowInsets) {
- val cutout = insets.displayCutout.also {
- this.cutout = it
- }
+ val cutout = insets.displayCutout.also { this.cutout = it }
val sbInsets: Pair<Int, Int> = insetsProvider.getStatusBarContentInsetsForCurrentRotation()
val cutoutLeft = sbInsets.first
@@ -373,8 +341,8 @@ class LargeScreenShadeHeaderController @Inject constructor(
updateQQSPaddings()
// Set these guides as the left/right limits for content that lives in the top row, using
// cutoutLeft and cutoutRight
- var changes = combinedShadeHeadersConstraintManager
- .edgesGuidelinesConstraints(
+ var changes =
+ combinedShadeHeadersConstraintManager.edgesGuidelinesConstraints(
if (view.isLayoutRtl) cutoutRight else cutoutLeft,
header.paddingStart,
if (view.isLayoutRtl) cutoutLeft else cutoutRight,
@@ -386,13 +354,14 @@ class LargeScreenShadeHeaderController @Inject constructor(
if (topCutout.isEmpty || hasCornerCutout) {
changes += combinedShadeHeadersConstraintManager.emptyCutoutConstraints()
} else {
- changes += combinedShadeHeadersConstraintManager.centerCutoutConstraints(
- view.isLayoutRtl,
- (view.width - view.paddingLeft - view.paddingRight - topCutout.width()) / 2
- )
+ changes +=
+ combinedShadeHeadersConstraintManager.centerCutoutConstraints(
+ view.isLayoutRtl,
+ (view.width - view.paddingLeft - view.paddingRight - topCutout.width()) / 2
+ )
}
} else {
- changes += combinedShadeHeadersConstraintManager.emptyCutoutConstraints()
+ changes += combinedShadeHeadersConstraintManager.emptyCutoutConstraints()
}
view.updateAllConstraints(changes)
@@ -406,7 +375,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun updateScrollY() {
- if (!largeScreenActive && combinedHeaders) {
+ if (!largeScreenActive) {
header.scrollY = qsScrollY
}
}
@@ -422,12 +391,6 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun onHeaderStateChanged() {
- if (largeScreenActive || combinedHeaders) {
- privacyIconsController.onParentVisible()
- } else {
- privacyIconsController.onParentInvisible()
- }
- updateVisibility()
updateTransition()
}
@@ -436,13 +399,14 @@ class LargeScreenShadeHeaderController @Inject constructor(
* be visible any time the QQS/QS shade is open.
*/
private fun updateVisibility() {
- val visibility = if (!largeScreenActive && !combinedHeaders || qsDisabled) {
- View.GONE
- } else if (qsVisible && !customizing) {
- View.VISIBLE
- } else {
- View.INVISIBLE
- }
+ val visibility =
+ if (qsDisabled) {
+ View.GONE
+ } else if (qsVisible && !customizing) {
+ View.VISIBLE
+ } else {
+ View.INVISIBLE
+ }
if (header.visibility != visibility) {
header.visibility = visibility
visible = visibility == View.VISIBLE
@@ -450,10 +414,6 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun updateTransition() {
- if (!combinedHeaders) {
- return
- }
- header as MotionLayout
if (largeScreenActive) {
logInstantEvent("Large screen constraints set")
header.setTransition(LARGE_SCREEN_HEADER_TRANSITION_ID)
@@ -467,7 +427,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun updatePosition() {
- if (header is MotionLayout && !largeScreenActive && visible) {
+ if (!largeScreenActive && visible) {
logInstantEvent("updatePosition: $qsExpandedFraction")
header.progress = qsExpandedFraction
updateBatteryMode()
@@ -475,11 +435,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun logInstantEvent(message: String) {
- Trace.instantForTrack(
- TRACE_TAG_APP,
- "LargeScreenHeaderController",
- message
- )
+ Trace.instantForTrack(TRACE_TAG_APP, "LargeScreenHeaderController", message)
}
private fun updateListeners() {
@@ -509,18 +465,16 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun updateQQSPaddings() {
- if (header is MotionLayout) {
- val clockPaddingStart = resources
- .getDimensionPixelSize(R.dimen.status_bar_left_clock_starting_padding)
- val clockPaddingEnd = resources
- .getDimensionPixelSize(R.dimen.status_bar_left_clock_end_padding)
- clock.setPaddingRelative(
- clockPaddingStart,
- clock.paddingTop,
- clockPaddingEnd,
- clock.paddingBottom
- )
- }
+ val clockPaddingStart =
+ resources.getDimensionPixelSize(R.dimen.status_bar_left_clock_starting_padding)
+ val clockPaddingEnd =
+ resources.getDimensionPixelSize(R.dimen.status_bar_left_clock_end_padding)
+ clock.setPaddingRelative(
+ clockPaddingStart,
+ clock.paddingTop,
+ clockPaddingEnd,
+ clock.paddingBottom
+ )
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
@@ -530,10 +484,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
pw.println("active: $largeScreenActive")
pw.println("qsExpandedFraction: $qsExpandedFraction")
pw.println("qsScrollY: $qsScrollY")
- if (combinedHeaders) {
- header as MotionLayout
- pw.println("currentState: ${header.currentState.stateToString()}")
- }
+ pw.println("currentState: ${header.currentState.stateToString()}")
}
private fun MotionLayout.updateConstraints(@IdRes state: Int, update: ConstraintChange) {
@@ -559,11 +510,10 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
}
- @VisibleForTesting
- internal fun simulateViewDetached() = this.onViewDetached()
+ @VisibleForTesting internal fun simulateViewDetached() = this.onViewDetached()
inner class CustomizerAnimationListener(
- private val enteringCustomizing: Boolean,
+ private val enteringCustomizing: Boolean,
) : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator?) {
super.onAnimationEnd(animation)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
index b28509e8fbf5..d34e127b194b 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
@@ -20,6 +20,9 @@ import android.view.MotionEvent
import com.android.systemui.log.dagger.ShadeLog
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.shade.NotificationPanelViewController.FLING_COLLAPSE
+import com.android.systemui.shade.NotificationPanelViewController.FLING_EXPAND
+import com.android.systemui.shade.NotificationPanelViewController.FLING_HIDE
import com.google.errorprone.annotations.CompileTimeConstant
import javax.inject.Inject
@@ -150,6 +153,17 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) {
)
}
+ fun logQsExpandImmediateChanged(newValue: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ bool1 = newValue
+ },
+ { "qsExpandImmediate=$bool1" }
+ )
+ }
+
fun logQsExpansionChanged(
message: String,
qsExpanded: Boolean,
@@ -230,18 +244,40 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) {
)
}
- fun logLastFlingWasExpanding(
- expand: Boolean
- ) {
+ fun logLastFlingWasExpanding(expand: Boolean) {
buffer.log(
- TAG,
- LogLevel.VERBOSE,
- {
- bool1 = expand
- },
- {
- "NPVC mLastFlingWasExpanding set to: $bool1"
- }
+ TAG,
+ LogLevel.VERBOSE,
+ { bool1 = expand },
+ { "NPVC mLastFlingWasExpanding set to: $bool1" }
+ )
+ }
+
+ fun flingQs(flingType: Int, isClick: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ str1 = flingTypeToString(flingType)
+ bool1 = isClick
+ },
+ { "QS fling with type $str1, originated from click: $isClick" }
+ )
+ }
+
+ private fun flingTypeToString(flingType: Int) = when (flingType) {
+ FLING_EXPAND -> "FLING_EXPAND"
+ FLING_COLLAPSE -> "FLING_COLLAPSE"
+ FLING_HIDE -> "FLING_HIDE"
+ else -> "UNKNOWN"
+ }
+
+ fun logSplitShadeChanged(splitShadeEnabled: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ { bool1 = splitShadeEnabled },
+ { "Split shade state changed: split shade ${if (bool1) "enabled" else "disabled"}" }
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenPortraitShadeInterpolator.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenPortraitShadeInterpolator.kt
new file mode 100644
index 000000000000..05191317e86b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenPortraitShadeInterpolator.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.transition
+
+import android.util.MathUtils
+import com.android.systemui.animation.ShadeInterpolation
+import javax.inject.Inject
+
+/** Interpolator responsible for the shade when in portrait on a large screen. */
+internal class LargeScreenPortraitShadeInterpolator @Inject internal constructor() :
+ LargeScreenShadeInterpolator {
+
+ override fun getBehindScrimAlpha(fraction: Float): Float {
+ return MathUtils.constrainedMap(0f, 1f, 0f, 0.3f, fraction)
+ }
+
+ override fun getNotificationScrimAlpha(fraction: Float): Float {
+ return MathUtils.constrainedMap(0f, 1f, 0.3f, 0.75f, fraction)
+ }
+
+ override fun getNotificationContentAlpha(fraction: Float): Float {
+ return ShadeInterpolation.getContentAlpha(fraction)
+ }
+
+ override fun getNotificationFooterAlpha(fraction: Float): Float {
+ return ShadeInterpolation.getContentAlpha(fraction)
+ }
+
+ override fun getQsAlpha(fraction: Float): Float {
+ return ShadeInterpolation.getContentAlpha(fraction)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolator.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolator.kt
new file mode 100644
index 000000000000..671dfc9c80ea
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolator.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.transition
+
+/** An interpolator interface for the shade expansion. */
+interface LargeScreenShadeInterpolator {
+
+ /** Returns the alpha for the behind/back scrim. */
+ fun getBehindScrimAlpha(fraction: Float): Float
+
+ /** Returns the alpha for the notification scrim. */
+ fun getNotificationScrimAlpha(fraction: Float): Float
+
+ /** Returns the alpha for the notifications. */
+ fun getNotificationContentAlpha(fraction: Float): Float
+
+ /** Returns the alpha for the notifications footer (Manager, Clear All). */
+ fun getNotificationFooterAlpha(fraction: Float): Float
+
+ /** Returns the alpha for the QS panel. */
+ fun getQsAlpha(fraction: Float): Float
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImpl.kt
new file mode 100644
index 000000000000..fd57f21b2e1e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImpl.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.transition
+
+import android.content.Context
+import android.content.res.Configuration
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.util.LargeScreenUtils
+import javax.inject.Inject
+
+/** Interpolator responsible for the shade when on large screens. */
+@SysUISingleton
+internal class LargeScreenShadeInterpolatorImpl
+@Inject
+internal constructor(
+ configurationController: ConfigurationController,
+ private val context: Context,
+ private val splitShadeInterpolator: SplitShadeInterpolator,
+ private val portraitShadeInterpolator: LargeScreenPortraitShadeInterpolator,
+) : LargeScreenShadeInterpolator {
+
+ private var inSplitShade = false
+
+ init {
+ configurationController.addCallback(
+ object : ConfigurationController.ConfigurationListener {
+ override fun onConfigChanged(newConfig: Configuration?) {
+ updateResources()
+ }
+ }
+ )
+ updateResources()
+ }
+
+ private fun updateResources() {
+ inSplitShade = LargeScreenUtils.shouldUseSplitNotificationShade(context.resources)
+ }
+
+ private val impl: LargeScreenShadeInterpolator
+ get() =
+ if (inSplitShade) {
+ splitShadeInterpolator
+ } else {
+ portraitShadeInterpolator
+ }
+
+ override fun getBehindScrimAlpha(fraction: Float) = impl.getBehindScrimAlpha(fraction)
+
+ override fun getNotificationScrimAlpha(fraction: Float) =
+ impl.getNotificationScrimAlpha(fraction)
+
+ override fun getNotificationContentAlpha(fraction: Float) =
+ impl.getNotificationContentAlpha(fraction)
+
+ override fun getNotificationFooterAlpha(fraction: Float) =
+ impl.getNotificationFooterAlpha(fraction)
+
+ override fun getQsAlpha(fraction: Float) = impl.getQsAlpha(fraction)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
index 218e897794fc..4e1c272ead99 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
@@ -23,6 +23,8 @@ import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.shade.PanelState
import com.android.systemui.shade.STATE_OPENING
import com.android.systemui.shade.ShadeExpansionChangeEvent
@@ -45,7 +47,8 @@ constructor(
private val scrimController: ScrimController,
@Main private val resources: Resources,
private val statusBarStateController: SysuiStatusBarStateController,
- private val headsUpManager: HeadsUpManager
+ private val headsUpManager: HeadsUpManager,
+ private val featureFlags: FeatureFlags,
) {
private var inSplitShade = false
@@ -106,7 +109,8 @@ constructor(
// in case of HUN we can't always use predefined distances to manage scrim
// transition because dragDownPxAmount can start from value bigger than
// splitShadeScrimTransitionDistance
- !headsUpManager.isTrackingHeadsUp
+ !headsUpManager.isTrackingHeadsUp &&
+ !featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)
private fun isScreenUnlocked() =
statusBarStateController.currentOrUpcomingState == StatusBarState.SHADE
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
index 07820ecd513e..129d09ec3c14 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
@@ -43,8 +43,6 @@ constructor(
shadeExpansionStateManager: ShadeExpansionStateManager,
dumpManager: DumpManager,
private val context: Context,
- private val splitShadeOverScrollerFactory: SplitShadeOverScroller.Factory,
- private val noOpOverScroller: NoOpOverScroller,
private val scrimShadeTransitionController: ScrimShadeTransitionController,
private val statusBarStateController: SysuiStatusBarStateController,
) {
@@ -57,17 +55,6 @@ constructor(
private var currentPanelState: Int? = null
private var lastShadeExpansionChangeEvent: ShadeExpansionChangeEvent? = null
- private val splitShadeOverScroller by lazy {
- splitShadeOverScrollerFactory.create({ qs }, { notificationStackScrollLayoutController })
- }
- private val shadeOverScroller: ShadeOverScroller
- get() =
- if (inSplitShade && isScreenUnlocked() && propertiesInitialized()) {
- splitShadeOverScroller
- } else {
- noOpOverScroller
- }
-
init {
updateResources()
configurationController.addCallback(
@@ -89,21 +76,14 @@ constructor(
private fun onPanelStateChanged(@PanelState state: Int) {
currentPanelState = state
- shadeOverScroller.onPanelStateChanged(state)
scrimShadeTransitionController.onPanelStateChanged(state)
}
private fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
lastShadeExpansionChangeEvent = event
- shadeOverScroller.onDragDownAmountChanged(event.dragDownPxAmount)
scrimShadeTransitionController.onPanelExpansionChanged(event)
}
- private fun propertiesInitialized() =
- this::qs.isInitialized &&
- this::notificationPanelViewController.isInitialized &&
- this::notificationStackScrollLayoutController.isInitialized
-
private fun dump(pw: PrintWriter) {
pw.println(
"""
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeInterpolator.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeInterpolator.kt
new file mode 100644
index 000000000000..423ba8d4ec88
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeInterpolator.kt
@@ -0,0 +1,63 @@
+/*
+ * 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.transition
+
+import android.util.MathUtils
+import javax.inject.Inject
+
+/** Interpolator responsible for the split shade. */
+internal class SplitShadeInterpolator @Inject internal constructor() :
+ LargeScreenShadeInterpolator {
+
+ override fun getBehindScrimAlpha(fraction: Float): Float {
+ // Start delay: 0%
+ // Duration: 40%
+ // End: 40%
+ return mapFraction(start = 0f, end = 0.4f, fraction)
+ }
+
+ override fun getNotificationScrimAlpha(fraction: Float): Float {
+ // Start delay: 39%
+ // Duration: 27%
+ // End: 66%
+ return mapFraction(start = 0.39f, end = 0.66f, fraction)
+ }
+
+ override fun getNotificationContentAlpha(fraction: Float): Float {
+ return getNotificationScrimAlpha(fraction)
+ }
+
+ override fun getNotificationFooterAlpha(fraction: Float): Float {
+ // Start delay: 57.6%
+ // Duration: 32.1%
+ // End: 89.7%
+ return mapFraction(start = 0.576f, end = 0.897f, fraction)
+ }
+
+ override fun getQsAlpha(fraction: Float): Float {
+ return getNotificationScrimAlpha(fraction)
+ }
+
+ private fun mapFraction(start: Float, end: Float, fraction: Float) =
+ MathUtils.constrainedMap(
+ /* rangeMin= */ 0f,
+ /* rangeMax= */ 1f,
+ /* valueMin= */ start,
+ /* valueMax= */ end,
+ /* value= */ fraction
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
deleted file mode 100644
index f95125f5cb6c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
+++ /dev/null
@@ -1,167 +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.systemui.shade.transition
-
-import android.animation.Animator
-import android.animation.ValueAnimator
-import android.content.Context
-import android.content.res.Configuration
-import android.util.MathUtils
-import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.PanelState
-import com.android.systemui.shade.STATE_CLOSED
-import com.android.systemui.shade.STATE_OPENING
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.policy.ConfigurationController
-import dagger.assisted.Assisted
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-import java.io.PrintWriter
-
-class SplitShadeOverScroller
-@AssistedInject
-constructor(
- configurationController: ConfigurationController,
- dumpManager: DumpManager,
- private val context: Context,
- private val scrimController: ScrimController,
- @Assisted private val qSProvider: () -> QS,
- @Assisted private val nsslControllerProvider: () -> NotificationStackScrollLayoutController
-) : ShadeOverScroller {
-
- private var releaseOverScrollDuration = 0L
- private var maxOverScrollAmount = 0
- private var previousOverscrollAmount = 0
- private var dragDownAmount: Float = 0f
- @PanelState private var panelState: Int = STATE_CLOSED
-
- private var releaseOverScrollAnimator: Animator? = null
-
- private val qS: QS
- get() = qSProvider()
-
- private val nsslController: NotificationStackScrollLayoutController
- get() = nsslControllerProvider()
-
- init {
- updateResources()
- configurationController.addCallback(
- object : ConfigurationController.ConfigurationListener {
- override fun onConfigChanged(newConfig: Configuration?) {
- updateResources()
- }
- })
- dumpManager.registerCriticalDumpable("SplitShadeOverScroller") { printWriter, _ ->
- dump(printWriter)
- }
- }
-
- private fun updateResources() {
- val resources = context.resources
- maxOverScrollAmount = resources.getDimensionPixelSize(R.dimen.shade_max_over_scroll_amount)
- releaseOverScrollDuration =
- resources.getInteger(R.integer.lockscreen_shade_over_scroll_release_duration).toLong()
- }
-
- override fun onPanelStateChanged(@PanelState newPanelState: Int) {
- if (shouldReleaseOverscroll(previousState = panelState, newState = newPanelState)) {
- releaseOverScroll()
- }
- panelState = newPanelState
- }
-
- override fun onDragDownAmountChanged(newDragDownAmount: Float) {
- if (dragDownAmount == newDragDownAmount) {
- return
- }
- dragDownAmount = newDragDownAmount
- if (shouldOverscroll()) {
- overScroll(newDragDownAmount)
- }
- }
-
- private fun shouldOverscroll() = panelState == STATE_OPENING
-
- private fun shouldReleaseOverscroll(@PanelState previousState: Int, @PanelState newState: Int) =
- previousState == STATE_OPENING && newState != STATE_OPENING
-
- private fun overScroll(dragDownAmount: Float) {
- val overscrollAmount: Int = calculateOverscrollAmount(dragDownAmount)
- applyOverscroll(overscrollAmount)
- previousOverscrollAmount = overscrollAmount
- }
-
- private fun calculateOverscrollAmount(dragDownAmount: Float): Int {
- val fullHeight: Int = nsslController.height
- val fullHeightProgress: Float = MathUtils.saturate(dragDownAmount / fullHeight)
- return (fullHeightProgress * maxOverScrollAmount).toInt()
- }
-
- private fun applyOverscroll(overscrollAmount: Int) {
- qS.setOverScrollAmount(overscrollAmount)
- scrimController.setNotificationsOverScrollAmount(overscrollAmount)
- nsslController.setOverScrollAmount(overscrollAmount)
- }
-
- private fun releaseOverScroll() {
- val animator = ValueAnimator.ofInt(previousOverscrollAmount, 0)
- animator.addUpdateListener {
- val overScrollAmount = it.animatedValue as Int
- qS.setOverScrollAmount(overScrollAmount)
- scrimController.setNotificationsOverScrollAmount(overScrollAmount)
- nsslController.setOverScrollAmount(overScrollAmount)
- }
- animator.interpolator = Interpolators.STANDARD
- animator.duration = releaseOverScrollDuration
- animator.start()
- releaseOverScrollAnimator = animator
- previousOverscrollAmount = 0
- }
-
- @VisibleForTesting
- internal fun finishAnimations() {
- releaseOverScrollAnimator?.end()
- releaseOverScrollAnimator = null
- }
-
- private fun dump(pw: PrintWriter) {
- pw.println(
- """
- SplitShadeOverScroller:
- Resources:
- releaseOverScrollDuration: $releaseOverScrollDuration
- maxOverScrollAmount: $maxOverScrollAmount
- State:
- previousOverscrollAmount: $previousOverscrollAmount
- dragDownAmount: $dragDownAmount
- panelState: $panelState
- """.trimIndent())
- }
-
- @AssistedFactory
- fun interface Factory {
- fun create(
- qSProvider: () -> QS,
- nsslControllerProvider: () -> NotificationStackScrollLayoutController
- ): SplitShadeOverScroller
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt
new file mode 100644
index 000000000000..37140ec2aa32
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.statusbar
+
+import android.annotation.IntRange
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.res.Configuration
+import android.util.AttributeSet
+import android.view.View
+import android.widget.FrameLayout
+import android.widget.LinearLayout
+import com.android.settingslib.Utils
+import com.android.systemui.R
+import com.android.systemui.battery.BatteryMeterView
+import com.android.systemui.statusbar.events.BackgroundAnimatableView
+
+class BatteryStatusChip @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
+ FrameLayout(context, attrs), BackgroundAnimatableView {
+
+ private val roundedContainer: LinearLayout
+ private val batteryMeterView: BatteryMeterView
+ override val contentView: View
+ get() = batteryMeterView
+
+ init {
+ inflate(context, R.layout.battery_status_chip, this)
+ roundedContainer = findViewById(R.id.rounded_container)
+ batteryMeterView = findViewById(R.id.battery_meter_view)
+ updateResources()
+ }
+
+ /**
+ * When animating as a chip in the status bar, we want to animate the width for the rounded
+ * container. We have to subtract our own top and left offset because the bounds come to us as
+ * absolute on-screen bounds.
+ */
+ override fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) {
+ roundedContainer.setLeftTopRightBottom(l - left, t - top, r - left, b - top)
+ }
+
+ fun setBatteryLevel(@IntRange(from = 0, to = 100) batteryLevel: Int) {
+ batteryMeterView.setForceShowPercent(true)
+ batteryMeterView.onBatteryLevelChanged(batteryLevel, true)
+ }
+
+ override fun onConfigurationChanged(newConfig: Configuration) {
+ super.onConfigurationChanged(newConfig)
+ updateResources()
+ }
+
+ @SuppressLint("UseCompatLoadingForDrawables")
+ private fun updateResources() {
+ val primaryColor =
+ Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
+ val textColorSecondary =
+ Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorSecondary)
+ batteryMeterView.updateColors(primaryColor, textColorSecondary, primaryColor)
+ roundedContainer.background = mContext.getDrawable(R.drawable.statusbar_chip_bg)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index f4782c2479b2..d5751f4a349f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -177,10 +177,12 @@ public class KeyguardIndicationController {
private boolean mVisible;
private boolean mOrganizationOwnedDevice;
+ // these all assume the device is plugged in (wired/wireless/docked) AND chargingOrFull:
private boolean mPowerPluggedIn;
private boolean mPowerPluggedInWired;
private boolean mPowerPluggedInWireless;
private boolean mPowerPluggedInDock;
+
private boolean mPowerCharged;
private boolean mBatteryOverheated;
private boolean mEnableBatteryDefender;
@@ -499,6 +501,7 @@ public class KeyguardIndicationController {
powerIndication += ", " + (mChargingWattage / 1000) + " mW";
}
+ mKeyguardLogger.logUpdateBatteryIndication(powerIndication, mPowerPluggedIn);
mRotateTextViewController.updateIndication(
INDICATION_TYPE_BATTERY,
new KeyguardIndication.Builder()
@@ -507,6 +510,7 @@ public class KeyguardIndicationController {
.build(),
animate);
} else {
+ mKeyguardLogger.log(TAG, LogLevel.DEBUG, "hide battery indication");
// don't show the charging information if device isn't plugged in
mRotateTextViewController.hideIndication(INDICATION_TYPE_BATTERY);
}
@@ -885,6 +889,9 @@ public class KeyguardIndicationController {
updateLockScreenIndications(animate, getCurrentUser());
}
+ /**
+ * Assumption: device is charging
+ */
protected String computePowerIndication() {
int chargingId;
if (mBatteryOverheated) {
@@ -1035,6 +1042,12 @@ public class KeyguardIndicationController {
}
}
+ /**
+ * KeyguardUpdateMonitor only sends "interesting" battery updates
+ * {@link KeyguardUpdateMonitor#isBatteryUpdateInteresting}.
+ * Therefore, make sure to always check plugged in state along with any charging status
+ * change, or else we could end up with stale state.
+ */
@Override
public void onRefreshBatteryInfo(BatteryStatus status) {
boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING
@@ -1050,7 +1063,9 @@ public class KeyguardIndicationController {
mBatteryLevel = status.level;
mBatteryPresent = status.present;
mBatteryOverheated = status.isOverheated();
+ // when the battery is overheated, device doesn't charge so only guard on pluggedIn:
mEnableBatteryDefender = mBatteryOverheated && status.isPluggedIn();
+
try {
mChargingTimeRemaining = mPowerPluggedIn
? mBatteryInfo.computeChargeTimeRemaining() : -1;
@@ -1058,14 +1073,10 @@ public class KeyguardIndicationController {
mKeyguardLogger.log(TAG, ERROR, "Error calling IBatteryStats", e);
mChargingTimeRemaining = -1;
}
+
+ mKeyguardLogger.logRefreshBatteryInfo(isChargingOrFull, mPowerPluggedIn, mBatteryLevel,
+ mBatteryOverheated);
updateDeviceEntryIndication(!wasPluggedIn && mPowerPluggedInWired);
- if (mDozing) {
- if (!wasPluggedIn && mPowerPluggedIn) {
- showTransientIndication(computePowerIndication());
- } else if (wasPluggedIn && !mPowerPluggedIn) {
- hideTransientIndication();
- }
- }
}
@Override
@@ -1317,6 +1328,10 @@ public class KeyguardIndicationController {
}
}
+ protected boolean isPluggedInAndCharging() {
+ return mPowerPluggedIn;
+ }
+
private boolean isCurrentUser(int userId) {
return getCurrentUser() == userId;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
index 62c225ba0b4e..df8c6abfff97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
@@ -148,7 +148,8 @@ constructor(
qsDragFraction: $qsTransitionFraction
qsSquishFraction: $qsSquishTransitionFraction
isTransitioningToFullShade: $isTransitioningToFullShade
- """.trimIndent()
+ """
+ .trimIndent()
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index f0d064b42d9c..9a9503c8cd9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -572,8 +572,7 @@ class LockscreenShadeTransitionController @Inject constructor(
entry.setGroupExpansionChanging(true)
userId = entry.sbn.userId
}
- var fullShadeNeedsBouncer = (!lockScreenUserManager.userAllowsPrivateNotificationsInPublic(
- lockScreenUserManager.getCurrentUserId()) ||
+ var fullShadeNeedsBouncer = (
!lockScreenUserManager.shouldShowLockscreenNotifications() ||
falsingCollector.shouldEnforceBouncer())
if (keyguardBypassController.bypassEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index f4cd985adbdb..51c5183ffee9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -213,7 +213,8 @@ public class NotificationLockscreenUserManagerImpl implements
DeviceProvisionedController deviceProvisionedController,
KeyguardStateController keyguardStateController,
SecureSettings secureSettings,
- DumpManager dumpManager) {
+ DumpManager dumpManager,
+ LockPatternUtils lockPatternUtils) {
mContext = context;
mMainHandler = mainHandler;
mDevicePolicyManager = devicePolicyManager;
@@ -225,7 +226,7 @@ public class NotificationLockscreenUserManagerImpl implements
mClickNotifier = clickNotifier;
mOverviewProxyServiceLazy = overviewProxyServiceLazy;
statusBarStateController.addCallback(this);
- mLockPatternUtils = new LockPatternUtils(context);
+ mLockPatternUtils = lockPatternUtils;
mKeyguardManager = keyguardManager;
mBroadcastDispatcher = broadcastDispatcher;
mDeviceProvisionedController = deviceProvisionedController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 8f1e0a1a6b16..3709a139e57d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -39,7 +39,10 @@ import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.ShadeInterpolation;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.notification.LegacySourceType;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.SourceType;
@@ -216,7 +219,15 @@ public class NotificationShelf extends ActivatableNotificationView implements
if (ambientState.isBouncerInTransit()) {
viewState.setAlpha(aboutToShowBouncerProgress(expansion));
} else {
- viewState.setAlpha(ShadeInterpolation.getContentAlpha(expansion));
+ FeatureFlags flags = ambientState.getFeatureFlags();
+ if (ambientState.isSmallScreen() || !flags.isEnabled(
+ Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+ viewState.setAlpha(ShadeInterpolation.getContentAlpha(expansion));
+ } else {
+ LargeScreenShadeInterpolator interpolator =
+ ambientState.getLargeScreenShadeInterpolator();
+ viewState.setAlpha(interpolator.getNotificationContentAlpha(expansion));
+ }
}
} else {
viewState.setAlpha(1f - ambientState.getHideAmount());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index c35c5c522798..77550038c94a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -93,6 +93,16 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
@IntDef({STATE_ICON, STATE_DOT, STATE_HIDDEN})
public @interface VisibleState { }
+ /** Returns a human-readable string of {@link VisibleState}. */
+ public static String getVisibleStateString(@VisibleState int state) {
+ switch(state) {
+ case STATE_ICON: return "ICON";
+ case STATE_DOT: return "DOT";
+ case STATE_HIDDEN: return "HIDDEN";
+ default: return "UNKNOWN";
+ }
+ }
+
private static final String TAG = "StatusBarIconView";
private static final Property<StatusBarIconView, Float> ICON_APPEAR_AMOUNT
= new FloatProperty<StatusBarIconView>("iconAppearAmount") {
@@ -561,7 +571,8 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
@Override
public String toString() {
return "StatusBarIconView("
- + "slot='" + mSlot + " alpha=" + getAlpha() + " icon=" + mIcon
+ + "slot='" + mSlot + "' alpha=" + getAlpha() + " icon=" + mIcon
+ + " visibleState=" + getVisibleStateString(getVisibleState())
+ " iconColor=#" + Integer.toHexString(mIconColor)
+ " notification=" + mNotification + ')';
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
index 42b874fd7156..7297ae689224 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
@@ -74,7 +74,7 @@ constructor(
/**
* @return a context with the MCC/MNC [Configuration] values corresponding to this
- * subscriptionId
+ * subscriptionId
*/
fun getMobileContextForSub(subId: Int, context: Context): Context {
if (demoModeController.isInDemoMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
index f25928418cbd..6a8d5c1fca9a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.events
-import android.animation.Animator
+import androidx.core.animation.Animator
import android.annotation.UiThread
import android.graphics.Point
import android.graphics.Rect
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
new file mode 100644
index 000000000000..3d6d48917dd3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
@@ -0,0 +1,71 @@
+/*
+ * 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.statusbar.events
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.time.SystemClock
+import dagger.Module
+import dagger.Provides
+import kotlinx.coroutines.CoroutineScope
+
+@Module
+interface StatusBarEventsModule {
+
+ companion object {
+
+ @Provides
+ @SysUISingleton
+ fun provideSystemStatusAnimationScheduler(
+ featureFlags: FeatureFlags,
+ coordinator: SystemEventCoordinator,
+ chipAnimationController: SystemEventChipAnimationController,
+ statusBarWindowController: StatusBarWindowController,
+ dumpManager: DumpManager,
+ systemClock: SystemClock,
+ @Application coroutineScope: CoroutineScope,
+ @Main executor: DelayableExecutor
+ ): SystemStatusAnimationScheduler {
+ return if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) {
+ SystemStatusAnimationSchedulerImpl(
+ coordinator,
+ chipAnimationController,
+ statusBarWindowController,
+ dumpManager,
+ systemClock,
+ coroutineScope
+ )
+ } else {
+ SystemStatusAnimationSchedulerLegacyImpl(
+ coordinator,
+ chipAnimationController,
+ statusBarWindowController,
+ dumpManager,
+ systemClock,
+ executor
+ )
+ }
+ }
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
index 4e1404d0637b..43f78c3166e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
@@ -16,24 +16,21 @@
package com.android.systemui.statusbar.events
+import android.annotation.IntRange
import android.annotation.SuppressLint
import android.content.Context
-import android.graphics.Color
-import android.graphics.drawable.ColorDrawable
-import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
-import com.android.settingslib.graph.ThemedBatteryDrawable
-import com.android.systemui.R
import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.privacy.PrivacyItem
+import com.android.systemui.statusbar.BatteryStatusChip
typealias ViewCreator = (context: Context) -> BackgroundAnimatableView
interface StatusEvent {
val priority: Int
// Whether or not to force the status bar open and show a dot
- val forceVisible: Boolean
+ var forceVisible: Boolean
// Whether or not to show an animation for this event
val showAnimation: Boolean
val viewCreator: ViewCreator
@@ -73,17 +70,16 @@ class BGImageView(
}
}
-class BatteryEvent : StatusEvent {
+class BatteryEvent(@IntRange(from = 0, to = 100) val batteryLevel: Int) : StatusEvent {
override val priority = 50
- override val forceVisible = false
+ override var forceVisible = false
override val showAnimation = true
override var contentDescription: String? = ""
- override val viewCreator: (context: Context) -> BGImageView = { context ->
- val iv = BGImageView(context)
- iv.setImageDrawable(ThemedBatteryDrawable(context, Color.WHITE))
- iv.setBackgroundDrawable(ColorDrawable(Color.GREEN))
- iv
+ override val viewCreator: ViewCreator = { context ->
+ BatteryStatusChip(context).apply {
+ setBatteryLevel(batteryLevel)
+ }
}
override fun toString(): String {
@@ -94,13 +90,12 @@ class BatteryEvent : StatusEvent {
class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
override var contentDescription: String? = null
override val priority = 100
- override val forceVisible = true
+ override var forceVisible = true
var privacyItems: List<PrivacyItem> = listOf()
private var privacyChip: OngoingPrivacyChip? = null
override val viewCreator: ViewCreator = { context ->
- val v = LayoutInflater.from(context)
- .inflate(R.layout.ongoing_privacy_chip, null) as OngoingPrivacyChip
+ val v = OngoingPrivacyChip(context)
v.privacyList = privacyItems
v.contentDescription = contentDescription
privacyChip = v
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
index 8405aea218f0..776956a20140 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
@@ -16,10 +16,6 @@
package com.android.systemui.statusbar.events
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.AnimatorSet
-import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Rect
import android.view.ContextThemeWrapper
@@ -30,7 +26,13 @@ import android.view.View.MeasureSpec.AT_MOST
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.FrameLayout
+import androidx.core.animation.Animator
+import androidx.core.animation.AnimatorListenerAdapter
+import androidx.core.animation.AnimatorSet
+import androidx.core.animation.ValueAnimator
import com.android.systemui.R
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.window.StatusBarWindowController
import com.android.systemui.util.animation.AnimationUtil.Companion.frames
@@ -43,7 +45,8 @@ import kotlin.math.roundToInt
class SystemEventChipAnimationController @Inject constructor(
private val context: Context,
private val statusBarWindowController: StatusBarWindowController,
- private val contentInsetsProvider: StatusBarContentInsetsProvider
+ private val contentInsetsProvider: StatusBarContentInsetsProvider,
+ private val featureFlags: FeatureFlags
) : SystemStatusAnimationCallback {
private lateinit var animationWindowView: FrameLayout
@@ -53,12 +56,14 @@ class SystemEventChipAnimationController @Inject constructor(
// Left for LTR, Right for RTL
private var animationDirection = LEFT
- private var chipRight = 0
- private var chipLeft = 0
- private var chipWidth = 0
+ private var chipBounds = Rect()
+ private val chipWidth get() = chipBounds.width()
+ private val chipRight get() = chipBounds.right
+ private val chipLeft get() = chipBounds.left
private var chipMinWidth = context.resources.getDimensionPixelSize(
R.dimen.ongoing_appops_chip_min_animation_width)
- private var dotSize = context.resources.getDimensionPixelSize(
+
+ private val dotSize = context.resources.getDimensionPixelSize(
R.dimen.ongoing_appops_dot_diameter)
// Use during animation so that multiple animators can update the drawing rect
private var animRect = Rect()
@@ -90,21 +95,26 @@ class SystemEventChipAnimationController @Inject constructor(
it.view.measure(
View.MeasureSpec.makeMeasureSpec(
(animationWindowView.parent as View).width, AT_MOST),
- View.MeasureSpec.makeMeasureSpec(animationWindowView.height, AT_MOST))
- chipWidth = it.chipWidth
- }
-
- // decide which direction we're animating from, and then set some screen coordinates
- val contentRect = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation()
- when (animationDirection) {
- LEFT -> {
- chipRight = contentRect.right
- chipLeft = contentRect.right - chipWidth
- }
- else /* RIGHT */ -> {
- chipLeft = contentRect.left
- chipRight = contentRect.left + chipWidth
+ View.MeasureSpec.makeMeasureSpec(
+ (animationWindowView.parent as View).height, AT_MOST))
+
+ // decide which direction we're animating from, and then set some screen coordinates
+ val contentRect = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation()
+ val chipTop = ((animationWindowView.parent as View).height - it.view.measuredHeight) / 2
+ val chipBottom = chipTop + it.view.measuredHeight
+ val chipRight: Int
+ val chipLeft: Int
+ when (animationDirection) {
+ LEFT -> {
+ chipRight = contentRect.right
+ chipLeft = contentRect.right - it.chipWidth
+ }
+ else /* RIGHT */ -> {
+ chipLeft = contentRect.left
+ chipRight = contentRect.left + it.chipWidth
+ }
}
+ chipBounds = Rect(chipLeft, chipTop, chipRight, chipBottom)
}
}
@@ -117,16 +127,21 @@ class SystemEventChipAnimationController @Inject constructor(
interpolator = null
addUpdateListener { currentAnimatedView?.view?.alpha = animatedValue as Float }
}
+ currentAnimatedView?.contentView?.alpha = 0f
+ val contentAlphaIn = ValueAnimator.ofFloat(0f, 1f).apply {
+ startDelay = 10.frames
+ duration = 10.frames
+ interpolator = null
+ addUpdateListener { currentAnimatedView?.contentView?.alpha = animatedValue as Float }
+ }
val moveIn = ValueAnimator.ofInt(chipMinWidth, chipWidth).apply {
startDelay = 7.frames
duration = 23.frames
interpolator = STATUS_BAR_X_MOVE_IN
- addUpdateListener {
- updateAnimatedViewBoundsWidth(animatedValue as Int)
- }
+ addUpdateListener { updateAnimatedViewBoundsWidth(animatedValue as Int) }
}
val animSet = AnimatorSet()
- animSet.playTogether(alphaIn, moveIn)
+ animSet.playTogether(alphaIn, contentAlphaIn, moveIn)
return animSet
}
@@ -139,7 +154,7 @@ class SystemEventChipAnimationController @Inject constructor(
}
finish.addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
+ override fun onAnimationEnd(animation: Animator) {
animationWindowView.removeView(currentAnimatedView!!.view)
}
})
@@ -152,7 +167,7 @@ class SystemEventChipAnimationController @Inject constructor(
duration = 9.frames
interpolator = STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_1
addUpdateListener {
- updateAnimatedViewBoundsWidth(it.animatedValue as Int)
+ updateAnimatedViewBoundsWidth(animatedValue as Int)
}
}
@@ -161,7 +176,7 @@ class SystemEventChipAnimationController @Inject constructor(
duration = 20.frames
interpolator = STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_2
addUpdateListener {
- updateAnimatedViewBoundsWidth(it.animatedValue as Int)
+ updateAnimatedViewBoundsWidth(animatedValue as Int)
}
}
@@ -174,7 +189,7 @@ class SystemEventChipAnimationController @Inject constructor(
duration = 6.frames
interpolator = STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_1
addUpdateListener {
- updateAnimatedViewBoundsHeight(it.animatedValue as Int, chipVerticalCenter)
+ updateAnimatedViewBoundsHeight(animatedValue as Int, chipVerticalCenter)
}
}
@@ -183,7 +198,7 @@ class SystemEventChipAnimationController @Inject constructor(
duration = 15.frames
interpolator = STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_2
addUpdateListener {
- updateAnimatedViewBoundsHeight(it.animatedValue as Int, chipVerticalCenter)
+ updateAnimatedViewBoundsHeight(animatedValue as Int, chipVerticalCenter)
}
}
@@ -210,15 +225,32 @@ class SystemEventChipAnimationController @Inject constructor(
}
private fun createMoveOutAnimationDefault(): Animator {
+ val alphaOut = ValueAnimator.ofFloat(1f, 0f).apply {
+ startDelay = 6.frames
+ duration = 6.frames
+ interpolator = null
+ addUpdateListener { currentAnimatedView?.view?.alpha = animatedValue as Float }
+ }
+
+ val contentAlphaOut = ValueAnimator.ofFloat(1f, 0f).apply {
+ duration = 5.frames
+ interpolator = null
+ addUpdateListener { currentAnimatedView?.contentView?.alpha = animatedValue as Float }
+ }
+
val moveOut = ValueAnimator.ofInt(chipWidth, chipMinWidth).apply {
duration = 23.frames
+ interpolator = STATUS_BAR_X_MOVE_OUT
addUpdateListener {
currentAnimatedView?.apply {
- updateAnimatedViewBoundsWidth(it.animatedValue as Int)
+ updateAnimatedViewBoundsWidth(animatedValue as Int)
}
}
}
- return moveOut
+
+ val animSet = AnimatorSet()
+ animSet.playTogether(alphaOut, contentAlphaOut, moveOut)
+ return animSet
}
private fun init() {
@@ -239,11 +271,15 @@ class SystemEventChipAnimationController @Inject constructor(
it.marginEnd = marginEnd
}
- private fun initializeAnimRect() = animRect.set(
- chipLeft,
- currentAnimatedView!!.view.top,
- chipRight,
- currentAnimatedView!!.view.bottom)
+ private fun initializeAnimRect() = if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) {
+ animRect.set(chipBounds)
+ } else {
+ animRect.set(
+ chipLeft,
+ currentAnimatedView!!.view.top,
+ chipRight,
+ currentAnimatedView!!.view.bottom)
+ }
/**
* To be called during an animation, sets the width and updates the current animated chip view
@@ -296,6 +332,8 @@ class SystemEventChipAnimationController @Inject constructor(
interface BackgroundAnimatableView {
val view: View // Since this can't extend View, add a view prop
get() = this as View
+ val contentView: View? // This will be alpha faded during appear and disappear animation
+ get() = null
val chipWidth: Int
get() = view.measuredWidth
fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
index fde5d39db7e3..26fd2307c59d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
@@ -16,11 +16,14 @@
package com.android.systemui.statusbar.events
+import android.annotation.IntRange
import android.content.Context
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_PRIVACY
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.privacy.PrivacyChipBuilder
import com.android.systemui.privacy.PrivacyItem
import com.android.systemui.privacy.PrivacyItemController
@@ -37,21 +40,18 @@ class SystemEventCoordinator @Inject constructor(
private val systemClock: SystemClock,
private val batteryController: BatteryController,
private val privacyController: PrivacyItemController,
- private val context: Context
+ private val context: Context,
+ private val featureFlags: FeatureFlags
) {
private lateinit var scheduler: SystemStatusAnimationScheduler
fun startObserving() {
- /* currently unused
batteryController.addCallback(batteryStateListener)
- */
privacyController.addCallback(privacyStateListener)
}
fun stopObserving() {
- /* currently unused
batteryController.removeCallback(batteryStateListener)
- */
privacyController.removeCallback(privacyStateListener)
}
@@ -59,12 +59,14 @@ class SystemEventCoordinator @Inject constructor(
this.scheduler = s
}
- fun notifyPluggedIn() {
- scheduler.onStatusEvent(BatteryEvent())
+ fun notifyPluggedIn(@IntRange(from = 0, to = 100) batteryLevel: Int) {
+ if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) {
+ scheduler.onStatusEvent(BatteryEvent(batteryLevel))
+ }
}
fun notifyPrivacyItemsEmpty() {
- scheduler.setShouldShowPersistentPrivacyIndicator(false)
+ scheduler.removePersistentDot()
}
fun notifyPrivacyItemsChanged(showAnimation: Boolean = true) {
@@ -79,25 +81,25 @@ class SystemEventCoordinator @Inject constructor(
}
private val batteryStateListener = object : BatteryController.BatteryStateChangeCallback {
- var plugged = false
- var stateKnown = false
+ private var plugged = false
+ private var stateKnown = false
override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
if (!stateKnown) {
stateKnown = true
plugged = pluggedIn
- notifyListeners()
+ notifyListeners(level)
return
}
if (plugged != pluggedIn) {
plugged = pluggedIn
- notifyListeners()
+ notifyListeners(level)
}
}
- private fun notifyListeners() {
+ private fun notifyListeners(@IntRange(from = 0, to = 100) batteryLevel: Int) {
// We only care about the plugged in status
- if (plugged) notifyPluggedIn()
+ if (plugged) notifyPluggedIn(batteryLevel)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
index 197cf5608cf5..2a18f1f51ace 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,302 +16,21 @@
package com.android.systemui.statusbar.events
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.AnimatorSet
import android.annotation.IntDef
-import android.os.Process
-import android.provider.DeviceConfig
-import android.util.Log
-import android.view.animation.PathInterpolator
+import androidx.core.animation.Animator
+import androidx.core.animation.AnimatorSet
+import androidx.core.animation.PathInterpolator
import com.android.systemui.Dumpable
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.policy.CallbackController
-import com.android.systemui.statusbar.window.StatusBarWindowController
-import com.android.systemui.util.Assert
-import com.android.systemui.util.concurrency.DelayableExecutor
-import com.android.systemui.util.time.SystemClock
-import java.io.PrintWriter
-import javax.inject.Inject
-/**
- * Dead-simple scheduler for system status events. Obeys the following principles (all values TBD):
- * - Avoiding log spam by only allowing 12 events per minute (1event/5s)
- * - Waits 100ms to schedule any event for debouncing/prioritization
- * - Simple prioritization: Privacy > Battery > connectivity (encoded in [StatusEvent])
- * - Only schedules a single event, and throws away lowest priority events
- *
- * There are 4 basic stages of animation at play here:
- * 1. System chrome animation OUT
- * 2. Chip animation IN
- * 3. Chip animation OUT; potentially into a dot
- * 4. System chrome animation IN
- *
- * Thus we can keep all animations synchronized with two separate ValueAnimators, one for system
- * chrome and the other for the chip. These can animate from 0,1 and listeners can parameterize
- * their respective views based on the progress of the animator. Interpolation differences TBD
- */
-@SysUISingleton
-open class SystemStatusAnimationScheduler @Inject constructor(
- private val coordinator: SystemEventCoordinator,
- private val chipAnimationController: SystemEventChipAnimationController,
- private val statusBarWindowController: StatusBarWindowController,
- private val dumpManager: DumpManager,
- private val systemClock: SystemClock,
- @Main private val executor: DelayableExecutor
-) : CallbackController<SystemStatusAnimationCallback>, Dumpable {
-
- companion object {
- private const val PROPERTY_ENABLE_IMMERSIVE_INDICATOR = "enable_immersive_indicator"
- }
- public fun isImmersiveIndicatorEnabled(): Boolean {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_ENABLE_IMMERSIVE_INDICATOR, true)
- }
-
- @SystemAnimationState var animationState: Int = IDLE
- private set
-
- /** True if the persistent privacy dot should be active */
- var hasPersistentDot = false
- protected set
-
- private var scheduledEvent: StatusEvent? = null
- private var cancelExecutionRunnable: Runnable? = null
- private val listeners = mutableSetOf<SystemStatusAnimationCallback>()
-
- fun getListeners(): MutableSet<SystemStatusAnimationCallback> {
- return listeners
- }
-
- init {
- coordinator.attachScheduler(this)
- dumpManager.registerDumpable(TAG, this)
- }
-
- open fun onStatusEvent(event: StatusEvent) {
- // Ignore any updates until the system is up and running
- if (isTooEarly() || !isImmersiveIndicatorEnabled()) {
- return
- }
-
- // Don't deal with threading for now (no need let's be honest)
- Assert.isMainThread()
- if ((event.priority > scheduledEvent?.priority ?: -1) &&
- animationState != ANIMATING_OUT &&
- (animationState != SHOWING_PERSISTENT_DOT && event.forceVisible)) {
- // events can only be scheduled if a higher priority or no other event is in progress
- if (DEBUG) {
- Log.d(TAG, "scheduling event $event")
- }
-
- scheduleEvent(event)
- } else if (scheduledEvent?.shouldUpdateFromEvent(event) == true) {
- if (DEBUG) {
- Log.d(TAG, "updating current event from: $event. animationState=$animationState")
- }
- scheduledEvent?.updateFromEvent(event)
- if (event.forceVisible) {
- hasPersistentDot = true
- // If we missed the chance to show the persistent dot, do it now
- if (animationState == IDLE) {
- notifyTransitionToPersistentDot()
- }
- }
- } else {
- if (DEBUG) {
- Log.d(TAG, "ignoring event $event")
- }
- }
- }
-
- private fun clearDotIfVisible() {
- notifyHidePersistentDot()
- }
-
- fun setShouldShowPersistentPrivacyIndicator(should: Boolean) {
- if (hasPersistentDot == should || !isImmersiveIndicatorEnabled()) {
- return
- }
-
- hasPersistentDot = should
-
- if (!hasPersistentDot) {
- clearDotIfVisible()
- }
- }
-
- public fun isTooEarly(): Boolean {
- return systemClock.uptimeMillis() - Process.getStartUptimeMillis() < MIN_UPTIME
- }
-
- /**
- * Clear the scheduled event (if any) and schedule a new one
- */
- private fun scheduleEvent(event: StatusEvent) {
- scheduledEvent = event
-
- if (event.forceVisible) {
- hasPersistentDot = true
- }
-
- // If animations are turned off, we'll transition directly to the dot
- if (!event.showAnimation && event.forceVisible) {
- notifyTransitionToPersistentDot()
- scheduledEvent = null
- return
- }
-
- chipAnimationController.prepareChipAnimation(scheduledEvent!!.viewCreator)
- animationState = ANIMATION_QUEUED
- executor.executeDelayed({
- runChipAnimation()
- }, DEBOUNCE_DELAY)
- }
-
- /**
- * 1. Define a total budget for the chip animation (1500ms)
- * 2. Send out callbacks to listeners so that they can generate animations locally
- * 3. Update the scheduler state so that clients know where we are
- * 4. Maybe: provide scaffolding such as: dot location, margins, etc
- * 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we
- * collect all of the animators and run them together.
- */
- private fun runChipAnimation() {
- statusBarWindowController.setForceStatusBarVisible(true)
- animationState = ANIMATING_IN
-
- val animSet = collectStartAnimations()
- if (animSet.totalDuration > 500) {
- throw IllegalStateException("System animation total length exceeds budget. " +
- "Expected: 500, actual: ${animSet.totalDuration}")
- }
- animSet.addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- animationState = RUNNING_CHIP_ANIM
- }
- })
- animSet.start()
-
- executor.executeDelayed({
- val animSet2 = collectFinishAnimations()
- animationState = ANIMATING_OUT
- animSet2.addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- animationState = if (hasPersistentDot) {
- SHOWING_PERSISTENT_DOT
- } else {
- IDLE
- }
-
- statusBarWindowController.setForceStatusBarVisible(false)
- }
- })
- animSet2.start()
- scheduledEvent = null
- }, DISPLAY_LENGTH)
- }
-
- private fun collectStartAnimations(): AnimatorSet {
- val animators = mutableListOf<Animator>()
- listeners.forEach { listener ->
- listener.onSystemEventAnimationBegin()?.let { anim ->
- animators.add(anim)
- }
- }
- animators.add(chipAnimationController.onSystemEventAnimationBegin())
- val animSet = AnimatorSet().also {
- it.playTogether(animators)
- }
-
- return animSet
- }
-
- private fun collectFinishAnimations(): AnimatorSet {
- val animators = mutableListOf<Animator>()
- listeners.forEach { listener ->
- listener.onSystemEventAnimationFinish(hasPersistentDot)?.let { anim ->
- animators.add(anim)
- }
- }
- animators.add(chipAnimationController.onSystemEventAnimationFinish(hasPersistentDot))
- if (hasPersistentDot) {
- val dotAnim = notifyTransitionToPersistentDot()
- if (dotAnim != null) {
- animators.add(dotAnim)
- }
- }
- val animSet = AnimatorSet().also {
- it.playTogether(animators)
- }
-
- return animSet
- }
-
- private fun notifyTransitionToPersistentDot(): Animator? {
- val anims: List<Animator> = listeners.mapNotNull {
- it.onSystemStatusAnimationTransitionToPersistentDot(scheduledEvent?.contentDescription)
- }
- if (anims.isNotEmpty()) {
- val aSet = AnimatorSet()
- aSet.playTogether(anims)
- return aSet
- }
-
- return null
- }
-
- private fun notifyHidePersistentDot(): Animator? {
- val anims: List<Animator> = listeners.mapNotNull {
- it.onHidePersistentDot()
- }
-
- if (animationState == SHOWING_PERSISTENT_DOT) {
- animationState = IDLE
- }
-
- if (anims.isNotEmpty()) {
- val aSet = AnimatorSet()
- aSet.playTogether(anims)
- return aSet
- }
+interface SystemStatusAnimationScheduler :
+ CallbackController<SystemStatusAnimationCallback>, Dumpable {
- return null
- }
+ @SystemAnimationState fun getAnimationState(): Int
- override fun addCallback(listener: SystemStatusAnimationCallback) {
- Assert.isMainThread()
-
- if (listeners.isEmpty()) {
- coordinator.startObserving()
- }
- listeners.add(listener)
- }
+ fun onStatusEvent(event: StatusEvent)
- override fun removeCallback(listener: SystemStatusAnimationCallback) {
- Assert.isMainThread()
-
- listeners.remove(listener)
- if (listeners.isEmpty()) {
- coordinator.stopObserving()
- }
- }
-
- override fun dump(pw: PrintWriter, args: Array<out String>) {
- pw.println("Scheduled event: $scheduledEvent")
- pw.println("Has persistent privacy dot: $hasPersistentDot")
- pw.println("Animation state: $animationState")
- pw.println("Listeners:")
- if (listeners.isEmpty()) {
- pw.println("(none)")
- } else {
- listeners.forEach {
- pw.println(" $it")
- }
- }
- }
+ fun removePersistentDot()
}
/**
@@ -337,6 +56,7 @@ interface SystemStatusAnimationCallback {
@JvmDefault fun onHidePersistentDot(): Animator? { return null }
}
+
/**
* Animation state IntDef
*/
@@ -354,7 +74,7 @@ interface SystemStatusAnimationCallback {
annotation class SystemAnimationState
/** No animation is in progress */
-const val IDLE = 0
+@SystemAnimationState const val IDLE = 0
/** An animation is queued, and awaiting the debounce period */
const val ANIMATION_QUEUED = 1
/** System is animating out, and chip is animating in */
@@ -379,20 +99,16 @@ val STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_1 = PathInterpolator(0.4f, 0f, 0.17f, 1f)
val STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_2 = PathInterpolator(0.3f, 0f, 0f, 1f)
val STATUS_CHIP_MOVE_TO_DOT = PathInterpolator(0f, 0f, 0.05f, 1f)
-private const val TAG = "SystemStatusAnimationScheduler"
-private const val DEBOUNCE_DELAY = 100L
+internal const val DEBOUNCE_DELAY = 100L
/**
* The total time spent on the chip animation is 1500ms, broken up into 3 sections:
- * - 500ms to animate the chip in (including animating system icons away)
- * - 500ms holding the chip on screen
- * - 500ms to animate the chip away (and system icons back)
- *
- * So DISPLAY_LENGTH should be the sum of the first 2 phases, while the final 500ms accounts for
- * the actual animation
+ * - 500ms to animate the chip in (including animating system icons away)
+ * - 500ms holding the chip on screen
+ * - 500ms to animate the chip away (and system icons back)
*/
-private const val DISPLAY_LENGTH = 1000L
-
-private const val MIN_UPTIME: Long = 5 * 1000
+internal const val APPEAR_ANIMATION_DURATION = 500L
+internal const val DISPLAY_LENGTH = 3000L
+internal const val DISAPPEAR_ANIMATION_DURATION = 500L
-private const val DEBUG = false
+internal const val MIN_UPTIME: Long = 5 * 1000 \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
new file mode 100644
index 000000000000..f7a4feafee25
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
@@ -0,0 +1,425 @@
+/*
+ * 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.statusbar.events
+
+import android.os.Process
+import android.provider.DeviceConfig
+import android.util.Log
+import androidx.core.animation.Animator
+import androidx.core.animation.AnimatorListenerAdapter
+import androidx.core.animation.AnimatorSet
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.Assert
+import com.android.systemui.util.time.SystemClock
+import java.io.PrintWriter
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.FlowPreview
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.debounce
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withTimeout
+
+/**
+ * Scheduler for system status events. Obeys the following principles:
+ * ```
+ * - Waits 100 ms to schedule any event for debouncing/prioritization
+ * - Simple prioritization: Privacy > Battery > Connectivity (encoded in [StatusEvent])
+ * - Only schedules a single event, and throws away lowest priority events
+ * ```
+ *
+ * There are 4 basic stages of animation at play here:
+ * ```
+ * 1. System chrome animation OUT
+ * 2. Chip animation IN
+ * 3. Chip animation OUT; potentially into a dot
+ * 4. System chrome animation IN
+ * ```
+ *
+ * Thus we can keep all animations synchronized with two separate ValueAnimators, one for system
+ * chrome and the other for the chip. These can animate from 0,1 and listeners can parameterize
+ * their respective views based on the progress of the animator.
+ */
+@OptIn(FlowPreview::class)
+open class SystemStatusAnimationSchedulerImpl
+@Inject
+constructor(
+ private val coordinator: SystemEventCoordinator,
+ private val chipAnimationController: SystemEventChipAnimationController,
+ private val statusBarWindowController: StatusBarWindowController,
+ dumpManager: DumpManager,
+ private val systemClock: SystemClock,
+ @Application private val coroutineScope: CoroutineScope
+) : SystemStatusAnimationScheduler {
+
+ companion object {
+ private const val PROPERTY_ENABLE_IMMERSIVE_INDICATOR = "enable_immersive_indicator"
+ }
+
+ /** Contains the StatusEvent that is going to be displayed next. */
+ private var scheduledEvent = MutableStateFlow<StatusEvent?>(null)
+
+ /**
+ * The currently displayed status event. (This is null in all states except ANIMATING_IN and
+ * CHIP_ANIMATION_RUNNING)
+ */
+ private var currentlyDisplayedEvent: StatusEvent? = null
+
+ /** StateFlow holding the current [SystemAnimationState] at any time. */
+ private var animationState = MutableStateFlow(IDLE)
+
+ /** True if the persistent privacy dot should be active */
+ var hasPersistentDot = false
+ protected set
+
+ /** Set of currently registered listeners */
+ protected val listeners = mutableSetOf<SystemStatusAnimationCallback>()
+
+ /** The job that is controlling the animators of the currently displayed status event. */
+ private var currentlyRunningAnimationJob: Job? = null
+
+ /** The job that is controlling the animators when an event is cancelled. */
+ private var eventCancellationJob: Job? = null
+
+ init {
+ coordinator.attachScheduler(this)
+ dumpManager.registerCriticalDumpable(TAG, this)
+
+ coroutineScope.launch {
+ // Wait for animationState to become ANIMATION_QUEUED and scheduledEvent to be non null.
+ // Once this combination is stable for at least DEBOUNCE_DELAY, then start a chip enter
+ // animation
+ animationState
+ .combine(scheduledEvent) { animationState, scheduledEvent ->
+ Pair(animationState, scheduledEvent)
+ }
+ .debounce(DEBOUNCE_DELAY)
+ .collect { (animationState, event) ->
+ if (animationState == ANIMATION_QUEUED && event != null) {
+ startAnimationLifecycle(event)
+ scheduledEvent.value = null
+ }
+ }
+ }
+ }
+
+ @SystemAnimationState override fun getAnimationState(): Int = animationState.value
+
+ override fun onStatusEvent(event: StatusEvent) {
+ Assert.isMainThread()
+
+ // Ignore any updates until the system is up and running
+ if (isTooEarly() || !isImmersiveIndicatorEnabled()) {
+ return
+ }
+
+ if (
+ (event.priority > (scheduledEvent.value?.priority ?: -1)) &&
+ (event.priority > (currentlyDisplayedEvent?.priority ?: -1)) &&
+ !hasPersistentDot
+ ) {
+ // a event can only be scheduled if no other event is in progress or it has a higher
+ // priority. If a persistent dot is currently displayed, don't schedule the event.
+ if (DEBUG) {
+ Log.d(TAG, "scheduling event $event")
+ }
+
+ scheduleEvent(event)
+ } else if (currentlyDisplayedEvent?.shouldUpdateFromEvent(event) == true) {
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "updating current event from: $event. animationState=${animationState.value}"
+ )
+ }
+ currentlyDisplayedEvent?.updateFromEvent(event)
+ } else if (scheduledEvent.value?.shouldUpdateFromEvent(event) == true) {
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "updating scheduled event from: $event. animationState=${animationState.value}"
+ )
+ }
+ scheduledEvent.value?.updateFromEvent(event)
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "ignoring event $event")
+ }
+ }
+ }
+
+ override fun removePersistentDot() {
+ Assert.isMainThread()
+
+ // If there is an event scheduled currently, set its forceVisible flag to false, such that
+ // it will never transform into a persistent dot
+ scheduledEvent.value?.forceVisible = false
+
+ // Nothing else to do if hasPersistentDot is already false
+ if (!hasPersistentDot) return
+ // Set hasPersistentDot to false. If the animationState is anything before ANIMATING_OUT,
+ // the disappear animation will not animate into a dot but remove the chip entirely
+ hasPersistentDot = false
+ // if we are currently showing a persistent dot, hide it
+ if (animationState.value == SHOWING_PERSISTENT_DOT) notifyHidePersistentDot()
+ // if we are currently animating into a dot, wait for the animation to finish and then hide
+ // the dot
+ if (animationState.value == ANIMATING_OUT) {
+ coroutineScope.launch {
+ withTimeout(DISAPPEAR_ANIMATION_DURATION) {
+ animationState.first { it == SHOWING_PERSISTENT_DOT || it == ANIMATION_QUEUED }
+ notifyHidePersistentDot()
+ }
+ }
+ }
+ }
+
+ protected fun isTooEarly(): Boolean {
+ return systemClock.uptimeMillis() - Process.getStartUptimeMillis() < MIN_UPTIME
+ }
+
+ protected fun isImmersiveIndicatorEnabled(): Boolean {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_ENABLE_IMMERSIVE_INDICATOR,
+ true
+ )
+ }
+
+ /** Clear the scheduled event (if any) and schedule a new one */
+ private fun scheduleEvent(event: StatusEvent) {
+ scheduledEvent.value = event
+ if (currentlyDisplayedEvent != null && eventCancellationJob?.isActive != true) {
+ // cancel the currently displayed event. As soon as the event is animated out, the
+ // scheduled event will be displayed.
+ cancelCurrentlyDisplayedEvent()
+ return
+ }
+ if (animationState.value == IDLE) {
+ // If we are in IDLE state, set it to ANIMATION_QUEUED now
+ animationState.value = ANIMATION_QUEUED
+ }
+ }
+
+ /**
+ * Cancels the currently displayed event by animating it out. This function should only be
+ * called if the animationState is ANIMATING_IN or RUNNING_CHIP_ANIM, or in other words whenever
+ * currentlyRunningEvent is not null
+ */
+ private fun cancelCurrentlyDisplayedEvent() {
+ eventCancellationJob =
+ coroutineScope.launch {
+ withTimeout(APPEAR_ANIMATION_DURATION) {
+ // wait for animationState to become RUNNING_CHIP_ANIM, then cancel the running
+ // animation job and run the disappear animation immediately
+ animationState.first { it == RUNNING_CHIP_ANIM }
+ currentlyRunningAnimationJob?.cancel()
+ runChipDisappearAnimation()
+ }
+ }
+ }
+
+ /**
+ * Takes the currently scheduled Event and (using the coroutineScope) animates it in and out
+ * again after displaying it for DISPLAY_LENGTH ms. This function should only be called if there
+ * is an event scheduled (and currentlyDisplayedEvent is null)
+ */
+ private fun startAnimationLifecycle(event: StatusEvent) {
+ Assert.isMainThread()
+ hasPersistentDot = event.forceVisible
+
+ if (!event.showAnimation && event.forceVisible) {
+ // If animations are turned off, we'll transition directly to the dot
+ animationState.value = SHOWING_PERSISTENT_DOT
+ notifyTransitionToPersistentDot()
+ return
+ }
+
+ currentlyDisplayedEvent = event
+
+ chipAnimationController.prepareChipAnimation(event.viewCreator)
+ currentlyRunningAnimationJob =
+ coroutineScope.launch {
+ runChipAppearAnimation()
+ delay(APPEAR_ANIMATION_DURATION + DISPLAY_LENGTH)
+ runChipDisappearAnimation()
+ }
+ }
+
+ /**
+ * 1. Define a total budget for the chip animation (1500ms)
+ * 2. Send out callbacks to listeners so that they can generate animations locally
+ * 3. Update the scheduler state so that clients know where we are
+ * 4. Maybe: provide scaffolding such as: dot location, margins, etc
+ * 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we
+ * collect all of the animators and run them together.
+ */
+ private fun runChipAppearAnimation() {
+ Assert.isMainThread()
+ if (hasPersistentDot) {
+ statusBarWindowController.setForceStatusBarVisible(true)
+ }
+ animationState.value = ANIMATING_IN
+
+ val animSet = collectStartAnimations()
+ if (animSet.totalDuration > 500) {
+ throw IllegalStateException(
+ "System animation total length exceeds budget. " +
+ "Expected: 500, actual: ${animSet.totalDuration}"
+ )
+ }
+ animSet.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ animationState.value = RUNNING_CHIP_ANIM
+ }
+ }
+ )
+ animSet.start()
+ }
+
+ private fun runChipDisappearAnimation() {
+ Assert.isMainThread()
+ val animSet2 = collectFinishAnimations()
+ animationState.value = ANIMATING_OUT
+ animSet2.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ animationState.value =
+ when {
+ hasPersistentDot -> SHOWING_PERSISTENT_DOT
+ scheduledEvent.value != null -> ANIMATION_QUEUED
+ else -> IDLE
+ }
+ statusBarWindowController.setForceStatusBarVisible(false)
+ }
+ }
+ )
+ animSet2.start()
+
+ // currentlyDisplayedEvent is set to null before the animation has ended such that new
+ // events can be scheduled during the disappear animation. We don't want to miss e.g. a new
+ // privacy event being scheduled during the disappear animation, otherwise we could end up
+ // with e.g. an active microphone but no privacy dot being displayed.
+ currentlyDisplayedEvent = null
+ }
+
+ private fun collectStartAnimations(): AnimatorSet {
+ val animators = mutableListOf<Animator>()
+ listeners.forEach { listener ->
+ listener.onSystemEventAnimationBegin()?.let { anim -> animators.add(anim) }
+ }
+ animators.add(chipAnimationController.onSystemEventAnimationBegin())
+
+ return AnimatorSet().also { it.playTogether(animators) }
+ }
+
+ private fun collectFinishAnimations(): AnimatorSet {
+ val animators = mutableListOf<Animator>()
+ listeners.forEach { listener ->
+ listener.onSystemEventAnimationFinish(hasPersistentDot)?.let { anim ->
+ animators.add(anim)
+ }
+ }
+ animators.add(chipAnimationController.onSystemEventAnimationFinish(hasPersistentDot))
+ if (hasPersistentDot) {
+ val dotAnim = notifyTransitionToPersistentDot()
+ if (dotAnim != null) {
+ animators.add(dotAnim)
+ }
+ }
+
+ return AnimatorSet().also { it.playTogether(animators) }
+ }
+
+ private fun notifyTransitionToPersistentDot(): Animator? {
+ val anims: List<Animator> =
+ listeners.mapNotNull {
+ it.onSystemStatusAnimationTransitionToPersistentDot(
+ currentlyDisplayedEvent?.contentDescription
+ )
+ }
+ if (anims.isNotEmpty()) {
+ val aSet = AnimatorSet()
+ aSet.playTogether(anims)
+ return aSet
+ }
+
+ return null
+ }
+
+ private fun notifyHidePersistentDot(): Animator? {
+ Assert.isMainThread()
+ val anims: List<Animator> = listeners.mapNotNull { it.onHidePersistentDot() }
+
+ if (animationState.value == SHOWING_PERSISTENT_DOT) {
+ if (scheduledEvent.value != null) {
+ animationState.value = ANIMATION_QUEUED
+ } else {
+ animationState.value = IDLE
+ }
+ }
+
+ if (anims.isNotEmpty()) {
+ val aSet = AnimatorSet()
+ aSet.playTogether(anims)
+ return aSet
+ }
+
+ return null
+ }
+
+ override fun addCallback(listener: SystemStatusAnimationCallback) {
+ Assert.isMainThread()
+
+ if (listeners.isEmpty()) {
+ coordinator.startObserving()
+ }
+ listeners.add(listener)
+ }
+
+ override fun removeCallback(listener: SystemStatusAnimationCallback) {
+ Assert.isMainThread()
+
+ listeners.remove(listener)
+ if (listeners.isEmpty()) {
+ coordinator.stopObserving()
+ }
+ }
+
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
+ pw.println("Scheduled event: ${scheduledEvent.value}")
+ pw.println("Currently displayed event: $currentlyDisplayedEvent")
+ pw.println("Has persistent privacy dot: $hasPersistentDot")
+ pw.println("Animation state: ${animationState.value}")
+ pw.println("Listeners:")
+ if (listeners.isEmpty()) {
+ pw.println("(none)")
+ } else {
+ listeners.forEach { pw.println(" $it") }
+ }
+ }
+}
+
+private const val DEBUG = false
+private const val TAG = "SystemStatusAnimationSchedulerImpl"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
new file mode 100644
index 000000000000..5fa83ef5d454
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.events
+
+import android.os.Process
+import android.provider.DeviceConfig
+import android.util.Log
+import androidx.core.animation.Animator
+import androidx.core.animation.AnimatorListenerAdapter
+import androidx.core.animation.AnimatorSet
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.Assert
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.time.SystemClock
+import java.io.PrintWriter
+import javax.inject.Inject
+
+/**
+ * Dead-simple scheduler for system status events. Obeys the following principles (all values TBD):
+ * ```
+ * - Avoiding log spam by only allowing 12 events per minute (1event/5s)
+ * - Waits 100ms to schedule any event for debouncing/prioritization
+ * - Simple prioritization: Privacy > Battery > connectivity (encoded in [StatusEvent])
+ * - Only schedules a single event, and throws away lowest priority events
+ * ```
+ *
+ * There are 4 basic stages of animation at play here:
+ * ```
+ * 1. System chrome animation OUT
+ * 2. Chip animation IN
+ * 3. Chip animation OUT; potentially into a dot
+ * 4. System chrome animation IN
+ * ```
+ *
+ * Thus we can keep all animations synchronized with two separate ValueAnimators, one for system
+ * chrome and the other for the chip. These can animate from 0,1 and listeners can parameterize
+ * their respective views based on the progress of the animator. Interpolation differences TBD
+ */
+open class SystemStatusAnimationSchedulerLegacyImpl
+@Inject
+constructor(
+ private val coordinator: SystemEventCoordinator,
+ private val chipAnimationController: SystemEventChipAnimationController,
+ private val statusBarWindowController: StatusBarWindowController,
+ private val dumpManager: DumpManager,
+ private val systemClock: SystemClock,
+ @Main private val executor: DelayableExecutor
+) : SystemStatusAnimationScheduler {
+
+ companion object {
+ private const val PROPERTY_ENABLE_IMMERSIVE_INDICATOR = "enable_immersive_indicator"
+ }
+
+ fun isImmersiveIndicatorEnabled(): Boolean {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_ENABLE_IMMERSIVE_INDICATOR,
+ true
+ )
+ }
+
+ @SystemAnimationState private var animationState: Int = IDLE
+
+ /** True if the persistent privacy dot should be active */
+ var hasPersistentDot = false
+ protected set
+
+ private var scheduledEvent: StatusEvent? = null
+
+ val listeners = mutableSetOf<SystemStatusAnimationCallback>()
+
+ init {
+ coordinator.attachScheduler(this)
+ dumpManager.registerDumpable(TAG, this)
+ }
+
+ @SystemAnimationState override fun getAnimationState() = animationState
+
+ override fun onStatusEvent(event: StatusEvent) {
+ // Ignore any updates until the system is up and running
+ if (isTooEarly() || !isImmersiveIndicatorEnabled()) {
+ return
+ }
+
+ // Don't deal with threading for now (no need let's be honest)
+ Assert.isMainThread()
+ if (
+ (event.priority > (scheduledEvent?.priority ?: -1)) &&
+ animationState != ANIMATING_OUT &&
+ animationState != SHOWING_PERSISTENT_DOT
+ ) {
+ // events can only be scheduled if a higher priority or no other event is in progress
+ if (DEBUG) {
+ Log.d(TAG, "scheduling event $event")
+ }
+
+ scheduleEvent(event)
+ } else if (scheduledEvent?.shouldUpdateFromEvent(event) == true) {
+ if (DEBUG) {
+ Log.d(TAG, "updating current event from: $event. animationState=$animationState")
+ }
+ scheduledEvent?.updateFromEvent(event)
+ if (event.forceVisible) {
+ hasPersistentDot = true
+ // If we missed the chance to show the persistent dot, do it now
+ if (animationState == IDLE) {
+ notifyTransitionToPersistentDot()
+ }
+ }
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "ignoring event $event")
+ }
+ }
+ }
+
+ override fun removePersistentDot() {
+ if (!hasPersistentDot || !isImmersiveIndicatorEnabled()) {
+ return
+ }
+
+ hasPersistentDot = false
+ notifyHidePersistentDot()
+ return
+ }
+
+ fun isTooEarly(): Boolean {
+ return systemClock.uptimeMillis() - Process.getStartUptimeMillis() < MIN_UPTIME
+ }
+
+ /** Clear the scheduled event (if any) and schedule a new one */
+ private fun scheduleEvent(event: StatusEvent) {
+ scheduledEvent = event
+
+ if (event.forceVisible) {
+ hasPersistentDot = true
+ }
+
+ // If animations are turned off, we'll transition directly to the dot
+ if (!event.showAnimation && event.forceVisible) {
+ notifyTransitionToPersistentDot()
+ scheduledEvent = null
+ return
+ }
+
+ chipAnimationController.prepareChipAnimation(scheduledEvent!!.viewCreator)
+ animationState = ANIMATION_QUEUED
+ executor.executeDelayed({ runChipAnimation() }, DEBOUNCE_DELAY)
+ }
+
+ /**
+ * 1. Define a total budget for the chip animation (1500ms)
+ * 2. Send out callbacks to listeners so that they can generate animations locally
+ * 3. Update the scheduler state so that clients know where we are
+ * 4. Maybe: provide scaffolding such as: dot location, margins, etc
+ * 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we
+ * collect all of the animators and run them together.
+ */
+ private fun runChipAnimation() {
+ statusBarWindowController.setForceStatusBarVisible(true)
+ animationState = ANIMATING_IN
+
+ val animSet = collectStartAnimations()
+ if (animSet.totalDuration > 500) {
+ throw IllegalStateException(
+ "System animation total length exceeds budget. " +
+ "Expected: 500, actual: ${animSet.totalDuration}"
+ )
+ }
+ animSet.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ animationState = RUNNING_CHIP_ANIM
+ }
+ }
+ )
+ animSet.start()
+
+ executor.executeDelayed(
+ {
+ val animSet2 = collectFinishAnimations()
+ animationState = ANIMATING_OUT
+ animSet2.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ animationState =
+ if (hasPersistentDot) {
+ SHOWING_PERSISTENT_DOT
+ } else {
+ IDLE
+ }
+
+ statusBarWindowController.setForceStatusBarVisible(false)
+ }
+ }
+ )
+ animSet2.start()
+ scheduledEvent = null
+ },
+ DISPLAY_LENGTH
+ )
+ }
+
+ private fun collectStartAnimations(): AnimatorSet {
+ val animators = mutableListOf<Animator>()
+ listeners.forEach { listener ->
+ listener.onSystemEventAnimationBegin()?.let { anim -> animators.add(anim) }
+ }
+ animators.add(chipAnimationController.onSystemEventAnimationBegin())
+ val animSet = AnimatorSet().also { it.playTogether(animators) }
+
+ return animSet
+ }
+
+ private fun collectFinishAnimations(): AnimatorSet {
+ val animators = mutableListOf<Animator>()
+ listeners.forEach { listener ->
+ listener.onSystemEventAnimationFinish(hasPersistentDot)?.let { anim ->
+ animators.add(anim)
+ }
+ }
+ animators.add(chipAnimationController.onSystemEventAnimationFinish(hasPersistentDot))
+ if (hasPersistentDot) {
+ val dotAnim = notifyTransitionToPersistentDot()
+ if (dotAnim != null) {
+ animators.add(dotAnim)
+ }
+ }
+ val animSet = AnimatorSet().also { it.playTogether(animators) }
+
+ return animSet
+ }
+
+ private fun notifyTransitionToPersistentDot(): Animator? {
+ val anims: List<Animator> =
+ listeners.mapNotNull {
+ it.onSystemStatusAnimationTransitionToPersistentDot(
+ scheduledEvent?.contentDescription
+ )
+ }
+ if (anims.isNotEmpty()) {
+ val aSet = AnimatorSet()
+ aSet.playTogether(anims)
+ return aSet
+ }
+
+ return null
+ }
+
+ private fun notifyHidePersistentDot(): Animator? {
+ val anims: List<Animator> = listeners.mapNotNull { it.onHidePersistentDot() }
+
+ if (animationState == SHOWING_PERSISTENT_DOT) {
+ animationState = IDLE
+ }
+
+ if (anims.isNotEmpty()) {
+ val aSet = AnimatorSet()
+ aSet.playTogether(anims)
+ return aSet
+ }
+
+ return null
+ }
+
+ override fun addCallback(listener: SystemStatusAnimationCallback) {
+ Assert.isMainThread()
+
+ if (listeners.isEmpty()) {
+ coordinator.startObserving()
+ }
+ listeners.add(listener)
+ }
+
+ override fun removeCallback(listener: SystemStatusAnimationCallback) {
+ Assert.isMainThread()
+
+ listeners.remove(listener)
+ if (listeners.isEmpty()) {
+ coordinator.stopObserving()
+ }
+ }
+
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
+ pw.println("Scheduled event: $scheduledEvent")
+ pw.println("Has persistent privacy dot: $hasPersistentDot")
+ pw.println("Animation state: $animationState")
+ pw.println("Listeners:")
+ if (listeners.isEmpty()) {
+ pw.println("(none)")
+ } else {
+ listeners.forEach { pw.println(" $it") }
+ }
+ }
+}
+
+private const val DEBUG = false
+private const val TAG = "SystemStatusAnimationSchedulerLegacyImpl"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index 6ef6165bcbb3..37538a3ca93b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -52,18 +52,19 @@ import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.WeatherData
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.regionsampling.RegionSampler
import com.android.systemui.shared.regionsampling.UpdateColorCallback
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DATE_SMARTSPACE_DATA_PLUGIN
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_SMARTSPACE_DATA_PLUGIN
-import com.android.systemui.plugins.Weather
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.util.concurrency.Execution
import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import java.time.Instant
import java.util.Optional
@@ -81,6 +82,7 @@ constructor(
private val smartspaceManager: SmartspaceManager,
private val activityStarter: ActivityStarter,
private val falsingManager: FalsingManager,
+ private val systemClock: SystemClock,
private val secureSettings: SecureSettings,
private val userTracker: UserTracker,
private val contentResolver: ContentResolver,
@@ -152,6 +154,18 @@ constructor(
// The weather data plugin takes unfiltered targets and performs the filtering internally.
weatherPlugin?.onTargetsAvailable(targets)
+ val now = Instant.ofEpochMilli(systemClock.currentTimeMillis())
+ val weatherTarget = targets.find { t ->
+ t.featureType == SmartspaceTarget.FEATURE_WEATHER &&
+ now.isAfter(Instant.ofEpochMilli(t.creationTimeMillis)) &&
+ now.isBefore(Instant.ofEpochMilli(t.expiryTimeMillis))
+ }
+ if (weatherTarget != null) {
+ val weatherData = WeatherData.fromBundle(weatherTarget.baseAction.extras)
+ if (weatherData != null) {
+ keyguardUpdateMonitor.sendWeatherData(weatherData)
+ }
+ }
val filteredTargets = targets.filter(::filterSmartspaceTarget)
plugin?.onTargetsAvailable(filteredTargets)
@@ -173,17 +187,6 @@ constructor(
}
isContentUpdatedOnce = true
}
-
- val now = Instant.now()
- val weatherTarget = targets.find { t ->
- t.featureType == SmartspaceTarget.FEATURE_WEATHER &&
- now.isAfter(Instant.ofEpochMilli(t.creationTimeMillis)) &&
- now.isBefore(Instant.ofEpochMilli(t.expiryTimeMillis))
- }
- if (weatherTarget != null) {
- val weatherData = Weather.fromBundle(weatherTarget.baseAction.extras)
- keyguardUpdateMonitor.sendWeatherData(weatherData)
- }
}
private val userTrackerCallback = object : UserTracker.Callback {
@@ -330,9 +333,9 @@ constructor(
}
val ssView = plugin.getView(parent)
+ configPlugin?.let { ssView.registerConfigProvider(it) }
ssView.setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
ssView.registerDataProvider(plugin)
- configPlugin?.let { ssView.registerConfigProvider(it) }
ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
@@ -497,8 +500,10 @@ constructor(
private fun updateTextColorFromRegionSampler() {
smartspaceViews.forEach {
- val textColor = regionSamplers.getValue(it).currentForegroundColor()
- it.setPrimaryTextColor(textColor)
+ val textColor = regionSamplers.get(it)?.currentForegroundColor()
+ if (textColor != null) {
+ it.setPrimaryTextColor(textColor)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 0a5e9867a17f..11582d7e3cc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -29,7 +29,6 @@ import android.app.AppGlobals;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
-import android.app.SynchronousUserSwitchObserver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -52,7 +51,9 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.CoreStartable;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.NotificationChannels;
@@ -73,6 +74,8 @@ public class InstantAppNotifier
private final Context mContext;
private final Handler mHandler = new Handler();
+ private final UserTracker mUserTracker;
+ private final Executor mMainExecutor;
private final Executor mUiBgExecutor;
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
private final CommandQueue mCommandQueue;
@@ -82,10 +85,14 @@ public class InstantAppNotifier
public InstantAppNotifier(
Context context,
CommandQueue commandQueue,
+ UserTracker userTracker,
+ @Main Executor mainExecutor,
@UiBackground Executor uiBgExecutor,
KeyguardStateController keyguardStateController) {
mContext = context;
mCommandQueue = commandQueue;
+ mUserTracker = userTracker;
+ mMainExecutor = mainExecutor;
mUiBgExecutor = uiBgExecutor;
mKeyguardStateController = keyguardStateController;
}
@@ -93,11 +100,7 @@ public class InstantAppNotifier
@Override
public void start() {
// listen for user / profile change.
- try {
- ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
- } catch (RemoteException e) {
- // Ignore
- }
+ mUserTracker.addCallback(mUserSwitchListener, mMainExecutor);
mCommandQueue.addCallback(this);
mKeyguardStateController.addCallback(this);
@@ -129,13 +132,10 @@ public class InstantAppNotifier
updateForegroundInstantApps();
}
- private final SynchronousUserSwitchObserver mUserSwitchListener =
- new SynchronousUserSwitchObserver() {
- @Override
- public void onUserSwitching(int newUserId) throws RemoteException {}
-
+ private final UserTracker.Callback mUserSwitchListener =
+ new UserTracker.Callback() {
@Override
- public void onUserSwitchComplete(int newUserId) throws RemoteException {
+ public void onUserChanged(int newUser, Context userContext) {
mHandler.post(
() -> {
updateForegroundInstantApps();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 7e53d5431353..8874f59d6c17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification
import android.animation.ObjectAnimator
import android.util.FloatProperty
+import androidx.annotation.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
@@ -302,29 +303,29 @@ class NotificationWakeUpCoordinator @Inject constructor(
// the doze amount to 0f (not dozing) so that the notifications are no longer hidden.
// See: UnlockedScreenOffAnimationController.onFinishedWakingUp()
setDozeAmount(0f, 0f, source = "Override: Shade->Shade (lock cancelled by unlock)")
+ this.state = newState
+ return
}
if (overrideDozeAmountIfAnimatingScreenOff(mLinearDozeAmount)) {
+ this.state = newState
return
}
if (overrideDozeAmountIfBypass()) {
+ this.state = newState
return
}
maybeClearDozeAmountOverrideHidingNotifs()
- if (bypassController.bypassEnabled &&
- newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED &&
- (!statusBarStateController.isDozing || shouldAnimateVisibility())) {
- // We're leaving shade locked. Let's animate the notifications away
- setNotificationsVisible(visible = true, increaseSpeed = false, animate = false)
- setNotificationsVisible(visible = false, increaseSpeed = false, animate = true)
- }
-
this.state = newState
}
+ @VisibleForTesting
+ val statusBarState: Int
+ get() = state
+
override fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
val collapsedEnough = event.fraction <= 0.9f
if (collapsedEnough != this.collapsedEnoughToHide) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
index 44645315ca80..88d9ffcdcf3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
@@ -13,7 +13,7 @@
package com.android.systemui.statusbar.notification
-import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.log.dagger.NotificationLockscreenLog
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel.DEBUG
import com.android.systemui.statusbar.StatusBarState
@@ -21,7 +21,12 @@ import javax.inject.Inject
class NotificationWakeUpCoordinatorLogger
@Inject
-constructor(@NotificationLog private val buffer: LogBuffer) {
+constructor(@NotificationLockscreenLog private val buffer: LogBuffer) {
+ private var lastSetDozeAmountLogWasFractional = false
+ private var lastSetDozeAmountLogState = -1
+ private var lastSetDozeAmountLogSource = "undefined"
+ private var lastOnDozeAmountChangedLogWasFractional = false
+
fun logSetDozeAmount(
linear: Float,
eased: Float,
@@ -29,6 +34,20 @@ constructor(@NotificationLog private val buffer: LogBuffer) {
state: Int,
changed: Boolean,
) {
+ // Avoid logging on every frame of the animation if important values are not changing
+ val isFractional = linear != 1f && linear != 0f
+ if (
+ lastSetDozeAmountLogWasFractional &&
+ isFractional &&
+ lastSetDozeAmountLogState == state &&
+ lastSetDozeAmountLogSource == source
+ ) {
+ return
+ }
+ lastSetDozeAmountLogWasFractional = isFractional
+ lastSetDozeAmountLogState = state
+ lastSetDozeAmountLogSource = source
+
buffer.log(
TAG,
DEBUG,
@@ -66,6 +85,10 @@ constructor(@NotificationLog private val buffer: LogBuffer) {
}
fun logOnDozeAmountChanged(linear: Float, eased: Float) {
+ // Avoid logging on every frame of the animation when values are fractional
+ val isFractional = linear != 1f && linear != 0f
+ if (lastOnDozeAmountChangedLogWasFractional && isFractional) return
+ lastOnDozeAmountChangedLogWasFractional = isFractional
buffer.log(
TAG,
DEBUG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
index a35617c88caf..6deef2e11828 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
@@ -315,6 +315,7 @@ interface Roundable {
/**
* State object for a `Roundable` class.
+ *
* @param targetView Will handle the [AnimatableProperty]
* @param roundable Target of the radius animation
* @param maxRadius Max corner radius in pixels
@@ -436,7 +437,6 @@ interface SourceType {
* This is the most convenient way to define a new [SourceType].
*
* For example:
- *
* ```kotlin
* private val SECTION = SourceType.from("Section")
* ```
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index df35c9e6832a..aa9a6c2c4cc6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -164,6 +164,11 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
private Queue<NotifEvent> mEventQueue = new ArrayDeque<>();
+ private final Runnable mRebuildListRunnable = () -> {
+ if (mBuildListener != null) {
+ mBuildListener.onBuildList(mReadOnlyNotificationSet, "asynchronousUpdate");
+ }
+ };
private boolean mAttached = false;
private boolean mAmDispatchingToOtherCode;
@@ -458,7 +463,7 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
int modificationType) {
Assert.isMainThread();
mEventQueue.add(new ChannelChangedEvent(pkgName, user, channel, modificationType));
- dispatchEventsAndRebuildList("onNotificationChannelModified");
+ dispatchEventsAndAsynchronouslyRebuildList();
}
private void onNotificationsInitialized() {
@@ -613,15 +618,39 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
private void dispatchEventsAndRebuildList(String reason) {
Trace.beginSection("NotifCollection.dispatchEventsAndRebuildList");
+ if (mMainHandler.hasCallbacks(mRebuildListRunnable)) {
+ mMainHandler.removeCallbacks(mRebuildListRunnable);
+ }
+
+ dispatchEvents();
+
+ if (mBuildListener != null) {
+ mBuildListener.onBuildList(mReadOnlyNotificationSet, reason);
+ }
+ Trace.endSection();
+ }
+
+ private void dispatchEventsAndAsynchronouslyRebuildList() {
+ Trace.beginSection("NotifCollection.dispatchEventsAndAsynchronouslyRebuildList");
+
+ dispatchEvents();
+
+ if (!mMainHandler.hasCallbacks(mRebuildListRunnable)) {
+ mMainHandler.postDelayed(mRebuildListRunnable, 1000L);
+ }
+
+ Trace.endSection();
+ }
+
+ private void dispatchEvents() {
+ Trace.beginSection("NotifCollection.dispatchEvents");
+
mAmDispatchingToOtherCode = true;
while (!mEventQueue.isEmpty()) {
mEventQueue.remove().dispatchTo(mNotifCollectionListeners);
}
mAmDispatchingToOtherCode = false;
- if (mBuildListener != null) {
- mBuildListener.onBuildList(mReadOnlyNotificationSet, reason);
- }
Trace.endSection();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
index cc1103de8ec0..abe067039cd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
@@ -20,6 +20,7 @@ package com.android.systemui.statusbar.notification.logging
import android.app.StatsManager
import android.util.Log
import android.util.StatsEvent
+import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -143,67 +144,70 @@ constructor(
runBlocking(mainDispatcher) {
traceSection("NML#getNotifications") { notificationPipeline.allNotifs }
}
+}
- /** Aggregates memory usage data by package and style, returning sums. */
- private fun aggregateMemoryUsageData(
- notificationMemoryUse: List<NotificationMemoryUsage>
- ): Map<Pair<String, Int>, NotificationMemoryUseAtomBuilder> {
- return notificationMemoryUse
- .groupingBy { Pair(it.packageName, it.objectUsage.style) }
- .aggregate {
- _,
- accumulator: NotificationMemoryUseAtomBuilder?,
- element: NotificationMemoryUsage,
- first ->
- val use =
- if (first) {
- NotificationMemoryUseAtomBuilder(element.uid, element.objectUsage.style)
- } else {
- accumulator!!
- }
-
- use.count++
- // If the views of the notification weren't inflated, the list of memory usage
- // parameters will be empty.
- if (element.viewUsage.isNotEmpty()) {
- use.countWithInflatedViews++
+/** Aggregates memory usage data by package and style, returning sums. */
+@VisibleForTesting
+internal fun aggregateMemoryUsageData(
+ notificationMemoryUse: List<NotificationMemoryUsage>
+): Map<Pair<String, Int>, NotificationMemoryLogger.NotificationMemoryUseAtomBuilder> {
+ return notificationMemoryUse
+ .groupingBy { Pair(it.packageName, it.objectUsage.style) }
+ .aggregate {
+ _,
+ accumulator: NotificationMemoryLogger.NotificationMemoryUseAtomBuilder?,
+ element: NotificationMemoryUsage,
+ first ->
+ val use =
+ if (first) {
+ NotificationMemoryLogger.NotificationMemoryUseAtomBuilder(
+ element.uid,
+ element.objectUsage.style
+ )
+ } else {
+ accumulator!!
}
- use.smallIconObject += element.objectUsage.smallIcon
- if (element.objectUsage.smallIcon > 0) {
- use.smallIconBitmapCount++
- }
+ use.count++
+ // If the views of the notification weren't inflated, the list of memory usage
+ // parameters will be empty.
+ if (element.viewUsage.isNotEmpty()) {
+ use.countWithInflatedViews++
+ }
- use.largeIconObject += element.objectUsage.largeIcon
- if (element.objectUsage.largeIcon > 0) {
- use.largeIconBitmapCount++
- }
+ use.smallIconObject += element.objectUsage.smallIcon
+ if (element.objectUsage.smallIcon > 0) {
+ use.smallIconBitmapCount++
+ }
- use.bigPictureObject += element.objectUsage.bigPicture
- if (element.objectUsage.bigPicture > 0) {
- use.bigPictureBitmapCount++
- }
+ use.largeIconObject += element.objectUsage.largeIcon
+ if (element.objectUsage.largeIcon > 0) {
+ use.largeIconBitmapCount++
+ }
- use.extras += element.objectUsage.extras
- use.extenders += element.objectUsage.extender
-
- // Use totals count which are more accurate when aggregated
- // in this manner.
- element.viewUsage
- .firstOrNull { vu -> vu.viewType == ViewType.TOTAL }
- ?.let {
- use.smallIconViews += it.smallIcon
- use.largeIconViews += it.largeIcon
- use.systemIconViews += it.systemIcons
- use.styleViews += it.style
- use.customViews += it.style
- use.softwareBitmaps += it.softwareBitmapsPenalty
- }
-
- return@aggregate use
+ use.bigPictureObject += element.objectUsage.bigPicture
+ if (element.objectUsage.bigPicture > 0) {
+ use.bigPictureBitmapCount++
}
- }
- /** Rounds the passed value to the nearest KB - e.g. 700B rounds to 1KB. */
- private fun toKb(value: Int): Int = (value.toFloat() / 1024f).roundToInt()
+ use.extras += element.objectUsage.extras
+ use.extenders += element.objectUsage.extender
+
+ // Use totals count which are more accurate when aggregated
+ // in this manner.
+ element.viewUsage
+ .firstOrNull { vu -> vu.viewType == ViewType.TOTAL }
+ ?.let {
+ use.smallIconViews += it.smallIcon
+ use.largeIconViews += it.largeIcon
+ use.systemIconViews += it.systemIcons
+ use.styleViews += it.style
+ use.customViews += it.customViews
+ use.softwareBitmaps += it.softwareBitmapsPenalty
+ }
+
+ return@aggregate use
+ }
}
+/** Rounds the passed value to the nearest KB - e.g. 700B rounds to 1KB. */
+private fun toKb(value: Int): Int = (value.toFloat() / 1024f).roundToInt()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 5a43f013159b..951db43ed6cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -153,7 +153,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
// We don't correctly track dark mode until the content views are inflated, so always update
// the background on first content update just in case it happens to be during a theme change.
private boolean mUpdateSelfBackgroundOnUpdate = true;
- private boolean mNotificationTranslationFinished = false;
private boolean mIsSnoozed;
private boolean mIsFaded;
private boolean mAnimatePinnedRoundness = false;
@@ -191,7 +190,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private int mMaxSmallHeightBeforeS;
private int mMaxSmallHeight;
private int mMaxSmallHeightLarge;
- private int mMaxSmallHeightMedia;
private int mMaxExpandedHeight;
private int mIncreasedPaddingBetweenElements;
private int mNotificationLaunchHeight;
@@ -210,11 +208,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
*/
private boolean mUserExpanded;
/**
- * Whether the blocking helper is showing on this notification (even if dismissed)
- */
- private boolean mIsBlockingHelperShowing;
-
- /**
* Has this notification been expanded while it was pinned
*/
private boolean mExpandedWhenPinned;
@@ -1566,18 +1559,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
- public void setBlockingHelperShowing(boolean isBlockingHelperShowing) {
- mIsBlockingHelperShowing = isBlockingHelperShowing;
- }
-
- public boolean isBlockingHelperShowing() {
- return mIsBlockingHelperShowing;
- }
-
- public boolean isBlockingHelperShowingAndTranslationFinished() {
- return mIsBlockingHelperShowing && mNotificationTranslationFinished;
- }
-
@Override
public View getShelfTransformationTarget() {
if (mIsSummaryWithChildren && !shouldShowPublic()) {
@@ -1771,8 +1752,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
R.dimen.notification_min_height);
mMaxSmallHeightLarge = NotificationUtils.getFontScaledHeight(mContext,
R.dimen.notification_min_height_increased);
- mMaxSmallHeightMedia = NotificationUtils.getFontScaledHeight(mContext,
- R.dimen.notification_min_height_media);
mMaxExpandedHeight = NotificationUtils.getFontScaledHeight(mContext,
R.dimen.notification_max_height);
mMaxHeadsUpHeightBeforeN = NotificationUtils.getFontScaledHeight(mContext,
@@ -2158,10 +2137,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
@Override
public void setTranslation(float translationX) {
invalidate();
- if (isBlockingHelperShowingAndTranslationFinished()) {
- mGuts.setTranslationX(translationX);
- return;
- } else if (mDismissUsingRowTranslationX) {
+ if (mDismissUsingRowTranslationX) {
setTranslationX(translationX);
} else if (mTranslateableViews != null) {
// Translate the group of views
@@ -2189,10 +2165,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return getTranslationX();
}
- if (isBlockingHelperShowingAndCanTranslate()) {
- return mGuts.getTranslationX();
- }
-
if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
// All of the views in the list should have same translation, just use first one.
return mTranslateableViews.get(0).getTranslationX();
@@ -2201,10 +2173,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return 0;
}
- private boolean isBlockingHelperShowingAndCanTranslate() {
- return areGutsExposed() && mIsBlockingHelperShowing && mNotificationTranslationFinished;
- }
-
public Animator getTranslateViewAnimator(final float leftTarget,
AnimatorUpdateListener listener) {
if (mTranslateAnim != null) {
@@ -2226,9 +2194,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
@Override
public void onAnimationEnd(Animator anim) {
- if (mIsBlockingHelperShowing) {
- mNotificationTranslationFinished = true;
- }
if (!cancelled && leftTarget == 0) {
if (mMenuRow != null) {
mMenuRow.resetMenu();
@@ -2808,9 +2773,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
int intrinsicBefore = getIntrinsicHeight();
mSensitive = sensitive;
mSensitiveHiddenInGeneral = hideSensitive;
- if (intrinsicBefore != getIntrinsicHeight()) {
- // The animation has a few flaws and is highly visible, so jump cut instead.
- notifyHeightChanged(false /* needsAnimation */);
+ int intrinsicAfter = getIntrinsicHeight();
+ if (intrinsicBefore != intrinsicAfter) {
+ boolean needsAnimation = mFeatureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM);
+ notifyHeightChanged(needsAnimation);
}
}
@@ -2867,13 +2833,19 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
View[] publicViews = new View[]{mPublicLayout};
View[] hiddenChildren = showingPublic ? privateViews : publicViews;
View[] shownChildren = showingPublic ? publicViews : privateViews;
+ // disappear/appear overlap: 10 percent of duration
+ long overlap = duration / 10;
+ // disappear duration: 1/3 of duration + half of overlap
+ long disappearDuration = duration / 3 + overlap / 2;
+ // appear duration: 2/3 of duration + half of overlap
+ long appearDuration = (duration - disappearDuration) + overlap / 2;
for (final View hiddenView : hiddenChildren) {
hiddenView.setVisibility(View.VISIBLE);
hiddenView.animate().cancel();
hiddenView.animate()
.alpha(0f)
.setStartDelay(delay)
- .setDuration(duration)
+ .setDuration(disappearDuration)
.withEndAction(() -> {
hiddenView.setVisibility(View.INVISIBLE);
resetAllContentAlphas();
@@ -2885,8 +2857,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
showView.animate().cancel();
showView.animate()
.alpha(1f)
- .setStartDelay(delay)
- .setDuration(duration);
+ .setStartDelay(delay + duration - appearDuration)
+ .setDuration(appearDuration);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index 39e4000c5d05..4522e41daf91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -443,6 +443,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
CancellationSignal cancellationSignal = new CancellationSignal();
cancellationSignal.setOnCancelListener(
() -> runningInflations.values().forEach(CancellationSignal::cancel));
+
return cancellationSignal;
}
@@ -783,6 +784,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
public static class AsyncInflationTask extends AsyncTask<Void, Void, InflationProgress>
implements InflationCallback, InflationTask {
+ private static final long IMG_PRELOAD_TIMEOUT_MS = 1000L;
private final NotificationEntry mEntry;
private final Context mContext;
private final boolean mInflateSynchronously;
@@ -876,7 +878,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
recoveredBuilder, mIsLowPriority, mUsesIncreasedHeight,
mUsesIncreasedHeadsUpHeight, packageContext);
InflatedSmartReplyState previousSmartReplyState = mRow.getExistingSmartReplyState();
- return inflateSmartReplyViews(
+ InflationProgress result = inflateSmartReplyViews(
inflationProgress,
mReInflateFlags,
mEntry,
@@ -884,6 +886,11 @@ public class NotificationContentInflater implements NotificationRowContentBinder
packageContext,
previousSmartReplyState,
mSmartRepliesInflater);
+
+ // wait for image resolver to finish preloading
+ mRow.getImageResolver().waitForPreloadedImages(IMG_PRELOAD_TIMEOUT_MS);
+
+ return result;
} catch (Exception e) {
mError = e;
return null;
@@ -918,6 +925,9 @@ public class NotificationContentInflater implements NotificationRowContentBinder
mCallback.handleInflationException(mRow.getEntry(),
new InflationException("Couldn't inflate contentViews" + e));
}
+
+ // Cancel any image loading tasks, not useful any more
+ mRow.getImageResolver().cancelRunningTasks();
}
@Override
@@ -944,6 +954,9 @@ public class NotificationContentInflater implements NotificationRowContentBinder
// Notify the resolver that the inflation task has finished,
// try to purge unnecessary cached entries.
mRow.getImageResolver().purgeCache();
+
+ // Cancel any image loading tasks that have not completed at this point
+ mRow.getImageResolver().cancelRunningTasks();
}
private static class RtlEnabledContext extends ContextWrapper {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index 93f08123ab5a..596bdc09efe4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -238,12 +238,11 @@ public class NotificationGuts extends FrameLayout {
}
public void openControls(
- boolean shouldDoCircularReveal,
int x,
int y,
boolean needsFalsingProtection,
@Nullable Runnable onAnimationEnd) {
- animateOpen(shouldDoCircularReveal, x, y, onAnimationEnd);
+ animateOpen(x, y, onAnimationEnd);
setExposed(true /* exposed */, needsFalsingProtection);
}
@@ -300,7 +299,7 @@ public class NotificationGuts extends FrameLayout {
if (mGutsContent == null
|| !mGutsContent.handleCloseControls(save, force)) {
// We only want to do a circular reveal if we're not showing the blocking helper.
- animateClose(x, y, true /* shouldDoCircularReveal */);
+ animateClose(x, y);
setExposed(false, mNeedsFalsingProtection);
if (mClosedListener != null) {
@@ -309,66 +308,45 @@ public class NotificationGuts extends FrameLayout {
}
}
- /** Animates in the guts view via either a fade or a circular reveal. */
- private void animateOpen(
- boolean shouldDoCircularReveal, int x, int y, @Nullable Runnable onAnimationEnd) {
+ /** Animates in the guts view with a circular reveal. */
+ private void animateOpen(int x, int y, @Nullable Runnable onAnimationEnd) {
if (isAttachedToWindow()) {
- if (shouldDoCircularReveal) {
- double horz = Math.max(getWidth() - x, x);
- double vert = Math.max(getHeight() - y, y);
- float r = (float) Math.hypot(horz, vert);
- // Make sure we'll be visible after the circular reveal
- setAlpha(1f);
- // Circular reveal originating at (x, y)
- Animator a = ViewAnimationUtils.createCircularReveal(this, x, y, 0, r);
- a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- a.addListener(new AnimateOpenListener(onAnimationEnd));
- a.start();
- } else {
- // Fade in content
- this.setAlpha(0f);
- this.animate()
- .alpha(1f)
- .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
- .setInterpolator(Interpolators.ALPHA_IN)
- .setListener(new AnimateOpenListener(onAnimationEnd))
- .start();
- }
+ double horz = Math.max(getWidth() - x, x);
+ double vert = Math.max(getHeight() - y, y);
+ float r = (float) Math.hypot(horz, vert);
+ // Make sure we'll be visible after the circular reveal
+ setAlpha(1f);
+ // Circular reveal originating at (x, y)
+ Animator a = ViewAnimationUtils.createCircularReveal(this, x, y, 0, r);
+ a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ a.addListener(new AnimateOpenListener(onAnimationEnd));
+ a.start();
+
} else {
Log.w(TAG, "Failed to animate guts open");
}
}
- /** Animates out the guts view via either a fade or a circular reveal. */
+ /** Animates out the guts view with a circular reveal. */
@VisibleForTesting
- void animateClose(int x, int y, boolean shouldDoCircularReveal) {
+ void animateClose(int x, int y) {
if (isAttachedToWindow()) {
- if (shouldDoCircularReveal) {
- // Circular reveal originating at (x, y)
- if (x == -1 || y == -1) {
- x = (getLeft() + getRight()) / 2;
- y = (getTop() + getHeight() / 2);
- }
- double horz = Math.max(getWidth() - x, x);
- double vert = Math.max(getHeight() - y, y);
- float r = (float) Math.hypot(horz, vert);
- Animator a = ViewAnimationUtils.createCircularReveal(this,
- x, y, r, 0);
- a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
- a.addListener(new AnimateCloseListener(this /* view */, mGutsContent));
- a.start();
- } else {
- // Fade in the blocking helper.
- this.animate()
- .alpha(0f)
- .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
- .setInterpolator(Interpolators.ALPHA_OUT)
- .setListener(new AnimateCloseListener(this, /* view */mGutsContent))
- .start();
+ // Circular reveal originating at (x, y)
+ if (x == -1 || y == -1) {
+ x = (getLeft() + getRight()) / 2;
+ y = (getTop() + getHeight() / 2);
}
+ double horz = Math.max(getWidth() - x, x);
+ double vert = Math.max(getHeight() - y, y);
+ float r = (float) Math.hypot(horz, vert);
+ Animator a = ViewAnimationUtils.createCircularReveal(this,
+ x, y, r, 0);
+ a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+ a.addListener(new AnimateCloseListener(this /* view */, mGutsContent));
+ a.start();
} else {
Log.w(TAG, "Failed to animate guts close");
mGutsContent.onFinishedClosing();
@@ -449,7 +427,7 @@ public class NotificationGuts extends FrameLayout {
return mGutsContent != null && mGutsContent.isLeavebehind();
}
- /** Listener for animations executed in {@link #animateOpen(boolean, int, int, Runnable)}. */
+ /** Listener for animations executed in {@link #animateOpen(int, int, Runnable)}. */
private static class AnimateOpenListener extends AnimatorListenerAdapter {
final Runnable mOnAnimationEnd;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 06d40803052e..46f1bb5ebd6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -629,7 +629,6 @@ public class NotificationGutsManager implements NotifGutsViewManager {
!mAccessibilityManager.isTouchExplorationEnabled());
guts.openControls(
- !row.isBlockingHelperShowing(),
x,
y,
needsFalsingProtection,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
index 41eeada0fcda..fe0b3123eb25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
@@ -22,8 +22,11 @@ import android.os.AsyncTask;
import android.util.Log;
import java.util.Set;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* A cache for inline images of image messages.
@@ -56,12 +59,13 @@ public class NotificationInlineImageCache implements NotificationInlineImageReso
}
@Override
- public Drawable get(Uri uri) {
+ public Drawable get(Uri uri, long timeoutMs) {
Drawable result = null;
try {
- result = mCache.get(uri).get();
- } catch (InterruptedException | ExecutionException ex) {
- Log.d(TAG, "get: Failed get image from " + uri);
+ result = mCache.get(uri).get(timeoutMs, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException | ExecutionException
+ | TimeoutException | CancellationException ex) {
+ Log.d(TAG, "get: Failed get image from " + uri + " " + ex);
}
return result;
}
@@ -72,6 +76,15 @@ public class NotificationInlineImageCache implements NotificationInlineImageReso
mCache.entrySet().removeIf(entry -> !wantedSet.contains(entry.getKey()));
}
+ @Override
+ public void cancelRunningTasks() {
+ mCache.forEach((key, value) -> {
+ if (value.getStatus() != AsyncTask.Status.FINISHED) {
+ value.cancel(true);
+ }
+ });
+ }
+
private static class PreloadImageTask extends AsyncTask<Uri, Void, Drawable> {
private final NotificationInlineImageResolver mResolver;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
index b05e64ab1991..c620f448b3b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
@@ -23,6 +23,7 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
+import android.os.SystemClock;
import android.util.Log;
import com.android.internal.R;
@@ -45,6 +46,9 @@ import java.util.Set;
public class NotificationInlineImageResolver implements ImageResolver {
private static final String TAG = NotificationInlineImageResolver.class.getSimpleName();
+ // Timeout for loading images from ImageCache when calling from UI thread
+ private static final long MAX_UI_THREAD_TIMEOUT_MS = 100L;
+
private final Context mContext;
private final ImageCache mImageCache;
private Set<Uri> mWantedUriSet;
@@ -123,17 +127,25 @@ public class NotificationInlineImageResolver implements ImageResolver {
return null;
}
+ /**
+ * Loads an image from the Uri.
+ * This method is synchronous and is usually called from the Main thread.
+ * It will time-out after MAX_UI_THREAD_TIMEOUT_MS.
+ *
+ * @param uri Uri of the target image.
+ * @return drawable of the image, null if loading failed/timeout
+ */
@Override
public Drawable loadImage(Uri uri) {
- return hasCache() ? loadImageFromCache(uri) : resolveImage(uri);
+ return hasCache() ? loadImageFromCache(uri, MAX_UI_THREAD_TIMEOUT_MS) : resolveImage(uri);
}
- private Drawable loadImageFromCache(Uri uri) {
+ private Drawable loadImageFromCache(Uri uri, long timeoutMs) {
// if the uri isn't currently cached, try caching it first
if (!mImageCache.hasEntry(uri)) {
mImageCache.preload((uri));
}
- return mImageCache.get(uri);
+ return mImageCache.get(uri, timeoutMs);
}
/**
@@ -208,6 +220,30 @@ public class NotificationInlineImageResolver implements ImageResolver {
}
/**
+ * Wait for a maximum timeout for images to finish preloading
+ * @param timeoutMs total timeout time
+ */
+ void waitForPreloadedImages(long timeoutMs) {
+ if (!hasCache()) {
+ return;
+ }
+ Set<Uri> preloadedUris = getWantedUriSet();
+ if (preloadedUris != null) {
+ // Decrement remaining timeout after each image check
+ long endTimeMs = SystemClock.elapsedRealtime() + timeoutMs;
+ preloadedUris.forEach(
+ uri -> loadImageFromCache(uri, endTimeMs - SystemClock.elapsedRealtime()));
+ }
+ }
+
+ void cancelRunningTasks() {
+ if (!hasCache()) {
+ return;
+ }
+ mImageCache.cancelRunningTasks();
+ }
+
+ /**
* A interface for internal cache implementation of this resolver.
*/
interface ImageCache {
@@ -216,7 +252,7 @@ public class NotificationInlineImageResolver implements ImageResolver {
* @param uri The uri of the image.
* @return Drawable of the image.
*/
- Drawable get(Uri uri);
+ Drawable get(Uri uri, long timeoutMs);
/**
* Set the image resolver that actually resolves image from specified uri.
@@ -241,6 +277,11 @@ public class NotificationInlineImageResolver implements ImageResolver {
* Purge unnecessary entries in the cache.
*/
void purge();
+
+ /**
+ * Cancel all unfinished image loading tasks
+ */
+ void cancelRunningTasks();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 6f4d6d944033..77ede0471603 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -29,6 +29,8 @@ import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -55,6 +57,8 @@ public class AmbientState implements Dumpable {
private final SectionProvider mSectionProvider;
private final BypassController mBypassController;
+ private final LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
+ private final FeatureFlags mFeatureFlags;
/**
* Used to read bouncer states.
*/
@@ -84,7 +88,7 @@ public class AmbientState implements Dumpable {
private float mExpandingVelocity;
private boolean mPanelTracking;
private boolean mExpansionChanging;
- private boolean mPanelFullWidth;
+ private boolean mIsSmallScreen;
private boolean mPulsing;
private boolean mUnlockHintRunning;
private float mHideAmount;
@@ -252,10 +256,14 @@ public class AmbientState implements Dumpable {
@NonNull DumpManager dumpManager,
@NonNull SectionProvider sectionProvider,
@NonNull BypassController bypassController,
- @Nullable StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+ @Nullable StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+ @NonNull LargeScreenShadeInterpolator largeScreenShadeInterpolator,
+ @NonNull FeatureFlags featureFlags) {
mSectionProvider = sectionProvider;
mBypassController = bypassController;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ mLargeScreenShadeInterpolator = largeScreenShadeInterpolator;
+ mFeatureFlags = featureFlags;
reload(context);
dumpManager.registerDumpable(this);
}
@@ -574,12 +582,12 @@ public class AmbientState implements Dumpable {
return mPanelTracking;
}
- public boolean isPanelFullWidth() {
- return mPanelFullWidth;
+ public boolean isSmallScreen() {
+ return mIsSmallScreen;
}
- public void setPanelFullWidth(boolean panelFullWidth) {
- mPanelFullWidth = panelFullWidth;
+ public void setSmallScreen(boolean smallScreen) {
+ mIsSmallScreen = smallScreen;
}
public void setUnlockHintRunning(boolean unlockHintRunning) {
@@ -736,6 +744,14 @@ public class AmbientState implements Dumpable {
return mIsClosing;
}
+ public LargeScreenShadeInterpolator getLargeScreenShadeInterpolator() {
+ return mLargeScreenShadeInterpolator;
+ }
+
+ public FeatureFlags getFeatureFlags() {
+ return mFeatureFlags;
+ }
+
@Override
public void dump(PrintWriter pw, String[] args) {
pw.println("mTopPadding=" + mTopPadding);
@@ -751,7 +767,7 @@ public class AmbientState implements Dumpable {
pw.println("mDimmed=" + mDimmed);
pw.println("mStatusBarState=" + mStatusBarState);
pw.println("mExpansionChanging=" + mExpansionChanging);
- pw.println("mPanelFullWidth=" + mPanelFullWidth);
+ pw.println("mPanelFullWidth=" + mIsSmallScreen);
pw.println("mPulsing=" + mPulsing);
pw.println("mPulseHeight=" + mPulseHeight);
pw.println("mTrackedHeadsUpRow.key=" + logKey(mTrackedHeadsUpRow));
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 1757a8380a48..e2e2a2382976 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
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.notification.stack;
-import static android.os.Trace.TRACE_TAG_ALWAYS;
+import static android.os.Trace.TRACE_TAG_APP;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_SHADE_CLEAR_ALL;
@@ -67,6 +67,7 @@ import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
+import android.view.WindowInsetsAnimation;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
@@ -199,6 +200,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private final boolean mDebugRemoveAnimation;
private final boolean mSimplifiedAppearFraction;
private final boolean mUseRoundnessSourceTypes;
+ private boolean mAnimatedInsets;
private int mContentHeight;
private float mIntrinsicContentHeight;
@@ -207,7 +209,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private int mTopPadding;
private boolean mAnimateNextTopPaddingChange;
private int mBottomPadding;
- private int mBottomInset = 0;
+ @VisibleForTesting
+ int mBottomInset = 0;
private float mQsExpansionFraction;
private final int mSplitShadeMinContentHeight;
@@ -388,9 +391,33 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
}
};
+
private boolean mPulsing;
private boolean mScrollable;
private View mForcedScroll;
+ private boolean mIsInsetAnimationRunning;
+
+ private final WindowInsetsAnimation.Callback mInsetsCallback =
+ new WindowInsetsAnimation.Callback(
+ WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
+
+ @Override
+ public void onPrepare(WindowInsetsAnimation animation) {
+ mIsInsetAnimationRunning = true;
+ }
+
+ @Override
+ public WindowInsets onProgress(WindowInsets windowInsets,
+ List<WindowInsetsAnimation> list) {
+ updateBottomInset(windowInsets);
+ return windowInsets;
+ }
+
+ @Override
+ public void onEnd(WindowInsetsAnimation animation) {
+ mIsInsetAnimationRunning = false;
+ }
+ };
/**
* @see #setHideAmount(float, float)
@@ -584,6 +611,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mDebugRemoveAnimation = featureFlags.isEnabled(Flags.NSSL_DEBUG_REMOVE_ANIMATION);
mSimplifiedAppearFraction = featureFlags.isEnabled(Flags.SIMPLIFIED_APPEAR_FRACTION);
mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
+ setAnimatedInsetsEnabled(featureFlags.isEnabled(Flags.ANIMATED_NOTIFICATION_SHADE_INSETS));
mSectionsManager = Dependency.get(NotificationSectionsManager.class);
mScreenOffAnimationController =
Dependency.get(ScreenOffAnimationController.class);
@@ -622,6 +650,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mGroupMembershipManager = Dependency.get(GroupMembershipManager.class);
mGroupExpansionManager = Dependency.get(GroupExpansionManager.class);
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+ if (mAnimatedInsets) {
+ setWindowInsetsAnimationCallback(mInsetsCallback);
+ }
}
/**
@@ -690,6 +721,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
@VisibleForTesting
+ void setAnimatedInsetsEnabled(boolean enabled) {
+ mAnimatedInsets = enabled;
+ }
+
+ @VisibleForTesting
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void updateFooter() {
if (mFooterView == null) {
@@ -1121,7 +1157,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@Override
public void requestLayout() {
- Trace.instant(TRACE_TAG_ALWAYS, "NotificationStackScrollLayout#requestLayout");
+ Trace.instant(TRACE_TAG_APP, "NotificationStackScrollLayout#requestLayout");
super.requestLayout();
}
@@ -1781,7 +1817,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
return;
}
mForcedScroll = v;
- scrollTo(v);
+ if (mAnimatedInsets) {
+ updateForcedScroll();
+ } else {
+ scrollTo(v);
+ }
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -1813,26 +1853,46 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
+ ((!isExpanded() && isPinnedHeadsUp(v)) ? mHeadsUpInset : getTopPadding());
}
+ private void updateBottomInset(WindowInsets windowInsets) {
+ mBottomInset = windowInsets.getInsets(WindowInsets.Type.ime()).bottom;
+
+ if (mForcedScroll != null) {
+ updateForcedScroll();
+ }
+
+ int range = getScrollRange();
+ if (mOwnScrollY > range) {
+ setOwnScrollY(range);
+ }
+ }
+
@Override
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mBottomInset = insets.getInsets(WindowInsets.Type.ime()).bottom;
+ if (!mAnimatedInsets) {
+ mBottomInset = insets.getInsets(WindowInsets.Type.ime()).bottom;
+ }
mWaterfallTopInset = 0;
final DisplayCutout cutout = insets.getDisplayCutout();
if (cutout != null) {
mWaterfallTopInset = cutout.getWaterfallInsets().top;
}
-
- int range = getScrollRange();
- if (mOwnScrollY > range) {
- // HACK: We're repeatedly getting staggered insets here while the IME is
- // animating away. To work around that we'll wait until things have settled.
- removeCallbacks(mReclamp);
- postDelayed(mReclamp, 50);
- } else if (mForcedScroll != null) {
- // The scroll was requested before we got the actual inset - in case we need
- // to scroll up some more do so now.
- scrollTo(mForcedScroll);
+ if (mAnimatedInsets && !mIsInsetAnimationRunning) {
+ // update bottom inset e.g. after rotation
+ updateBottomInset(insets);
+ }
+ if (!mAnimatedInsets) {
+ int range = getScrollRange();
+ if (mOwnScrollY > range) {
+ // HACK: We're repeatedly getting staggered insets here while the IME is
+ // animating away. To work around that we'll wait until things have settled.
+ removeCallbacks(mReclamp);
+ postDelayed(mReclamp, 50);
+ } else if (mForcedScroll != null) {
+ // The scroll was requested before we got the actual inset - in case we need
+ // to scroll up some more do so now.
+ scrollTo(mForcedScroll);
+ }
}
return insets;
}
@@ -5163,7 +5223,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void setIsFullWidth(boolean isFullWidth) {
- mAmbientState.setPanelFullWidth(isFullWidth);
+ mAmbientState.setSmallScreen(isFullWidth);
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 42d122d6f9ac..02621fe4c103 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -70,7 +70,6 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEv
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeController;
-import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
@@ -171,7 +170,6 @@ public class NotificationStackScrollLayoutController {
private final CentralSurfaces mCentralSurfaces;
private final SectionHeaderController mSilentHeaderController;
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
- private final ShadeTransitionController mShadeTransitionController;
private final InteractionJankMonitor mJankMonitor;
private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
private final StackStateLogger mStackStateLogger;
@@ -209,7 +207,11 @@ public class NotificationStackScrollLayoutController {
public void onViewAttachedToWindow(View v) {
mConfigurationController.addCallback(mConfigurationListener);
mZenModeController.addCallback(mZenModeControllerCallback);
- mBarState = mStatusBarStateController.getState();
+ final int newBarState = mStatusBarStateController.getState();
+ if (newBarState != mBarState) {
+ mStateListener.onStateChanged(newBarState);
+ mStateListener.onStatePostChange();
+ }
mStatusBarStateController.addCallback(
mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
}
@@ -658,7 +660,6 @@ public class NotificationStackScrollLayoutController {
NotifPipelineFlags notifPipelineFlags,
NotifCollection notifCollection,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
- ShadeTransitionController shadeTransitionController,
UiEventLogger uiEventLogger,
NotificationRemoteInputManager remoteInputManager,
VisibilityLocationProviderDelegator visibilityLocationProviderDelegator,
@@ -690,7 +691,6 @@ public class NotificationStackScrollLayoutController {
mMetricsLogger = metricsLogger;
mDumpManager = dumpManager;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
- mShadeTransitionController = shadeTransitionController;
mFalsingCollector = falsingCollector;
mFalsingManager = falsingManager;
mResources = resources;
@@ -773,7 +773,6 @@ public class NotificationStackScrollLayoutController {
mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming);
mLockscreenShadeTransitionController.setStackScroller(this);
- mShadeTransitionController.setNotificationStackScrollLayoutController(this);
mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index aaf9300e7cc8..c6f56d482d43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -251,13 +251,13 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc
|| (isFastNonDismissGesture && isAbleToShowMenu);
int menuSnapTarget = menuRow.getMenuSnapTarget();
boolean isNonFalseMenuRevealingGesture =
- !isFalseGesture() && isMenuRevealingGestureAwayFromMenu;
+ isMenuRevealingGestureAwayFromMenu && !isFalseGesture();
if ((isNonDismissGestureTowardsMenu || isNonFalseMenuRevealingGesture)
&& menuSnapTarget != 0) {
// Menu has not been snapped to previously and this is menu revealing gesture
snapOpen(animView, menuSnapTarget, velocity);
menuRow.onSnapOpen();
- } else if (isDismissGesture(ev) && !gestureTowardsMenu) {
+ } else if (isDismissGesture && !gestureTowardsMenu) {
dismiss(animView, velocity);
menuRow.onDismiss();
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
index 548d1a135948..8b6d6a4f3170 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
@@ -25,9 +25,10 @@ constructor(
/**
* This method looks for views that can be rounded (and implement [Roundable]) during a
* notification swipe.
+ *
* @return The [Roundable] targets above/below the [viewSwiped] (if available). The
- * [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
- * no above/below notification or the notification is not part of the same section.
+ * [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
+ * no above/below notification or the notification is not part of the same section.
*/
fun findRoundableTargets(
viewSwiped: ExpandableNotificationRow,
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 a425792f6523..5516edeac344 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
@@ -29,6 +29,9 @@ import com.android.internal.policy.SystemBarUtils;
import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.systemui.R;
import com.android.systemui.animation.ShadeInterpolation;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.LegacySourceType;
@@ -135,7 +138,6 @@ public class StackScrollAlgorithm {
AmbientState ambientState) {
for (ExpandableView view : algorithmState.visibleChildren) {
final ViewState viewState = view.getViewState();
-
final boolean isHunGoingToShade = ambientState.isShadeExpanded()
&& view == ambientState.getTrackedHeadsUpRow();
@@ -148,9 +150,14 @@ public class StackScrollAlgorithm {
} else if (ambientState.isExpansionChanging()) {
// Adjust alpha for shade open & close.
float expansion = ambientState.getExpansionFraction();
- viewState.setAlpha(ambientState.isBouncerInTransit()
- ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
- : ShadeInterpolation.getContentAlpha(expansion));
+ if (ambientState.isBouncerInTransit()) {
+ viewState.setAlpha(
+ BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion));
+ } else if (view instanceof FooterView) {
+ viewState.setAlpha(interpolateFooterAlpha(ambientState));
+ } else {
+ viewState.setAlpha(interpolateNotificationContentAlpha(ambientState));
+ }
}
// For EmptyShadeView if on keyguard, we need to control the alpha to create
@@ -182,6 +189,28 @@ public class StackScrollAlgorithm {
}
}
+ private float interpolateFooterAlpha(AmbientState ambientState) {
+ float expansion = ambientState.getExpansionFraction();
+ FeatureFlags flags = ambientState.getFeatureFlags();
+ if (ambientState.isSmallScreen()
+ || !flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+ return ShadeInterpolation.getContentAlpha(expansion);
+ }
+ LargeScreenShadeInterpolator interpolator = ambientState.getLargeScreenShadeInterpolator();
+ return interpolator.getNotificationFooterAlpha(expansion);
+ }
+
+ private float interpolateNotificationContentAlpha(AmbientState ambientState) {
+ float expansion = ambientState.getExpansionFraction();
+ FeatureFlags flags = ambientState.getFeatureFlags();
+ if (ambientState.isSmallScreen()
+ || !flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+ return ShadeInterpolation.getContentAlpha(expansion);
+ }
+ LargeScreenShadeInterpolator interpolator = ambientState.getLargeScreenShadeInterpolator();
+ return interpolator.getNotificationContentAlpha(expansion);
+ }
+
/**
* How expanded or collapsed notifications are when pulling down the shade.
*
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 576df7ac7add..f6d53b3bc9b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -31,7 +31,7 @@ import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.AutoAddTracker;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.ReduceBrightColorsController;
import com.android.systemui.qs.SettingObserver;
import com.android.systemui.qs.external.CustomTile;
@@ -75,7 +75,7 @@ public class AutoTileManager implements UserAwareController {
private final String mSafetySpec;
protected final Context mContext;
- protected final QSTileHost mHost;
+ protected final QSHost mHost;
protected final Handler mHandler;
protected final SecureSettings mSecureSettings;
protected final AutoAddTracker mAutoTracker;
@@ -92,7 +92,7 @@ public class AutoTileManager implements UserAwareController {
private final ArrayList<AutoAddSetting> mAutoAddSettingList = new ArrayList<>();
public AutoTileManager(Context context, AutoAddTracker.Builder autoAddTrackerBuilder,
- QSTileHost host,
+ QSHost host,
@Background Handler handler,
SecureSettings secureSettings,
HotspotController hotspotController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index db2c0a08c1d9..573347cb1aff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -383,10 +383,24 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
}
@Override
+ public void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+ boolean isStrongBiometric) {
+ Trace.beginSection("BiometricUnlockController#onBiometricDetected");
+ if (mUpdateMonitor.isGoingToSleep()) {
+ Trace.endSection();
+ return;
+ }
+ startWakeAndUnlock(MODE_SHOW_BOUNCER);
+ }
+
+ @Override
public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
boolean isStrongBiometric) {
Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
if (mUpdateMonitor.isGoingToSleep()) {
+ mLogger.deferringAuthenticationDueToSleep(userId,
+ biometricSourceType,
+ mPendingAuthenticated != null);
mPendingAuthenticated = new PendingAuthenticated(userId, biometricSourceType,
isStrongBiometric);
Trace.endSection();
@@ -802,6 +816,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
public void onFinishedGoingToSleep() {
Trace.beginSection("BiometricUnlockController#onFinishedGoingToSleep");
if (mPendingAuthenticated != null) {
+ mLogger.finishedGoingToSleepWithPendingAuth();
PendingAuthenticated pendingAuthenticated = mPendingAuthenticated;
// Post this to make sure it's executed after the device is fully locked.
mHandler.post(() -> onBiometricAuthenticated(pendingAuthenticated.userId,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index 4d0ad405835a..311728fff6aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -372,8 +372,6 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn
void fadeKeyguardAfterLaunchTransition(Runnable beforeFading,
Runnable endRunnable, Runnable cancelRunnable);
- void animateKeyguardUnoccluding();
-
void startLaunchTransitionTimeout();
boolean hideKeyguardImpl(boolean forceStateChange);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index b8ab956b32d3..df850ae42712 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -53,6 +53,7 @@ import com.android.systemui.camera.CameraIntents;
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QSPanelController;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.CameraLauncher;
@@ -106,6 +107,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
private final SystemBarAttributesListener mSystemBarAttributesListener;
private final Lazy<CameraLauncher> mCameraLauncherLazy;
private final QuickSettingsController mQsController;
+ private final QSHost mQSHost;
private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
@@ -138,7 +140,8 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
@DisplayId int displayId,
SystemBarAttributesListener systemBarAttributesListener,
Lazy<CameraLauncher> cameraLauncherLazy,
- UserTracker userTracker) {
+ UserTracker userTracker,
+ QSHost qsHost) {
mCentralSurfaces = centralSurfaces;
mQsController = quickSettingsController;
mContext = context;
@@ -164,6 +167,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
mDisplayId = displayId;
mCameraLauncherLazy = cameraLauncherLazy;
mUserTracker = userTracker;
+ mQSHost = qsHost;
mVibrateOnOpening = resources.getBoolean(R.bool.config_vibrateOnIconAnimation);
mCameraLaunchGestureVibrationEffect = getCameraGestureVibrationEffect(
@@ -184,22 +188,17 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
@Override
public void addQsTile(ComponentName tile) {
- QSPanelController qsPanelController = mCentralSurfaces.getQSPanelController();
- if (qsPanelController != null && qsPanelController.getHost() != null) {
- qsPanelController.getHost().addTile(tile);
- }
+ mQSHost.addTile(tile);
}
@Override
public void remQsTile(ComponentName tile) {
- QSPanelController qsPanelController = mCentralSurfaces.getQSPanelController();
- if (qsPanelController != null && qsPanelController.getHost() != null) {
- qsPanelController.getHost().removeTileByUser(tile);
- }
+ mQSHost.removeTileByUser(tile);
}
@Override
public void clickTile(ComponentName tile) {
+ // Can't inject this because it changes with the QS fragment
QSPanelController qsPanelController = mCentralSurfaces.getQSPanelController();
if (qsPanelController != null) {
qsPanelController.clickTile(tile);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 378b74a62024..5131772e34a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -605,7 +605,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
private Runnable mLaunchTransitionEndRunnable;
private Runnable mLaunchTransitionCancelRunnable;
- private boolean mLaunchingAffordance;
private boolean mLaunchCameraWhenFinishedWaking;
private boolean mLaunchCameraOnFinishedGoingToSleep;
private boolean mLaunchEmergencyActionWhenFinishedWaking;
@@ -2211,10 +2210,10 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
pw.println("Current Status Bar state:");
pw.println(" mExpandedVisible=" + mShadeController.isExpandedVisible());
pw.println(" mDisplayMetrics=" + mDisplayMetrics);
- pw.println(" mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
- pw.println(" mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller)
- + " scroll " + mStackScroller.getScrollX()
+ pw.print(" mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
+ pw.print(" scroll " + mStackScroller.getScrollX()
+ "," + mStackScroller.getScrollY());
+ pw.println(" translationX " + mStackScroller.getTranslationX());
}
pw.print(" mInteractingWindows="); pw.println(mInteractingWindows);
@@ -2984,16 +2983,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
}
/**
- * Plays the animation when an activity that was occluding Keyguard goes away.
- */
- @Override
- public void animateKeyguardUnoccluding() {
- mNotificationPanelViewController.setExpandedFraction(0f);
- mCommandQueueCallbacks.animateExpandNotificationsPanel();
- mScrimController.setUnocclusionAnimationRunning(true);
- }
-
- /**
* Starts the timeout when we try to start the affordances on Keyguard. We usually rely that
* Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen
* because the launched app crashed or something else went wrong.
@@ -3581,7 +3570,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
boolean goingToSleepWithoutAnimation = isGoingToSleep()
&& !mDozeParameters.shouldControlScreenOff();
boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing())
- || goingToSleepWithoutAnimation;
+ || goingToSleepWithoutAnimation
+ || mDeviceProvisionedController.isFrpActive();
mNotificationPanelViewController.setTouchAndAnimationDisabled(disabled);
mNotificationIconAreaController.setAnimationsEnabled(!disabled);
}
@@ -3705,6 +3695,12 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
@Override
public void notifyBiometricAuthModeChanged() {
mDozeServiceHost.updateDozing();
+ if (mBiometricUnlockController.getMode()
+ == BiometricUnlockController.MODE_DISMISS_BOUNCER) {
+ // Don't update the scrim controller at this time, in favor of the transition repository
+ // updating the scrim
+ return;
+ }
updateScrimController();
}
@@ -3747,16 +3743,17 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mScrimController.setExpansionAffectsAlpha(!unlocking);
- boolean launchingAffordanceWithPreview = mLaunchingAffordance;
- mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
-
if (mAlternateBouncerInteractor.isVisibleState()) {
- if (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
- || mTransitionToFullShadeProgress > 0f) {
+ if ((!isOccluded() || isPanelExpanded())
+ && (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
+ || mTransitionToFullShadeProgress > 0f)) {
mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE);
} else {
mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
}
+ // This will cancel the keyguardFadingAway animation if it is running. We need to do
+ // this as otherwise it can remain pending and leave keyguard in a weird state.
+ mUnlockScrimCallback.onCancelled();
} else if (mBouncerShowing && !unlocking) {
// Bouncer needs the front scrim when it's on top of an activity,
// tapping on a notification, editing QS or being dismissed by
@@ -3764,9 +3761,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
ScrimState state = mStatusBarKeyguardViewManager.primaryBouncerNeedsScrimming()
? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
mScrimController.transitionTo(state);
- } else if (launchingAffordanceWithPreview) {
- // We want to avoid animating when launching with a preview.
- mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
} else if (mBrightnessMirrorVisible) {
mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
} else if (mState == StatusBarState.SHADE_LOCKED) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index c72eb054c62c..39b5b5a4cef8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -40,6 +40,7 @@ import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger;
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView;
@@ -288,10 +289,14 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
* @param mobileContext possibly mcc/mnc overridden mobile context
* @param subId the subscriptionId for this mobile view
*/
- public void addModernMobileView(Context mobileContext, int subId) {
+ public void addModernMobileView(
+ Context mobileContext,
+ MobileViewLogger mobileViewLogger,
+ int subId) {
Log.d(TAG, "addModernMobileView (subId=" + subId + ")");
ModernStatusBarMobileView view = ModernStatusBarMobileView.constructAndBind(
mobileContext,
+ mobileViewLogger,
"mobile",
mMobileIconsViewModel.viewModelForSub(subId, mLocation)
);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index b88531e59568..ae715b3f20c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -429,7 +429,6 @@ public class DozeParameters implements
}
dispatchAlwaysOnEvent();
- mScreenOffAnimationController.onAlwaysOnChanged(getAlwaysOn());
}
@Override
@@ -469,6 +468,7 @@ public class DozeParameters implements
for (Callback callback : mCallbacks) {
callback.onAlwaysOnChange();
}
+ mScreenOffAnimationController.onAlwaysOnChanged(getAlwaysOn());
}
private boolean getPostureSpecificBool(
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 b1553b0d306f..9d30cb4c4852 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -76,6 +76,7 @@ public class KeyguardIndicationTextView extends TextView {
if (mLastAnimator != null) {
mLastAnimator.cancel();
}
+ mMessage = "";
setText("");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index cba0897408dd..3268032becf8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -21,9 +21,6 @@ import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -36,13 +33,16 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
+import androidx.core.animation.Animator;
+import androidx.core.animation.AnimatorListenerAdapter;
+import androidx.core.animation.ValueAnimator;
import com.android.keyguard.CarrierTextController;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
+import com.android.systemui.animation.InterpolatorsAndroidX;
import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.log.LogLevel;
@@ -59,7 +59,7 @@ import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.fragment.StatusBarIconBlocklistKt;
-import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventAnimator;
+import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventDefaultAnimator;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -75,6 +75,8 @@ import java.util.concurrent.Executor;
import javax.inject.Inject;
+import kotlin.Unit;
+
/** View Controller for {@link com.android.systemui.statusbar.phone.KeyguardStatusBarView}. */
public class KeyguardStatusBarViewController extends ViewController<KeyguardStatusBarView> {
private static final String TAG = "KeyguardStatusBarViewController";
@@ -123,7 +125,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
public void onDensityOrFontScaleChanged() {
mView.loadDimens();
// The animator is dependent on resources for offsets
- mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, getResources());
+ mSystemEventAnimator =
+ getSystemEventAnimator(mSystemEventAnimator.isAnimationRunning());
}
@Override
@@ -166,7 +169,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
private final ValueAnimator.AnimatorUpdateListener mAnimatorUpdateListener =
animation -> {
- mKeyguardStatusBarAnimateAlpha = (float) animation.getAnimatedValue();
+ mKeyguardStatusBarAnimateAlpha =
+ (float) ((ValueAnimator) animation).getAnimatedValue();
updateViewState();
};
@@ -247,7 +251,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
private int mStatusBarState;
private boolean mDozing;
private boolean mShowingKeyguardHeadsUp;
- private StatusBarSystemEventAnimator mSystemEventAnimator;
+ private StatusBarSystemEventDefaultAnimator mSystemEventAnimator;
+ private float mSystemEventAnimatorAlpha = 1;
/**
* The alpha value to be set on the View. If -1, this value is to be ignored.
@@ -323,7 +328,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
mView.setKeyguardUserAvatarEnabled(
!mStatusBarUserChipViewModel.getChipEnabled());
- mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, r);
+ mSystemEventAnimator = getSystemEventAnimator(/* isAnimationRunning */ false);
mDisableStateTracker = new DisableStateTracker(
/* mask1= */ DISABLE_SYSTEM_INFO,
@@ -434,7 +439,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
anim.addUpdateListener(mAnimatorUpdateListener);
anim.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- anim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ anim.setInterpolator(InterpolatorsAndroidX.LINEAR_OUT_SLOW_IN);
anim.start();
}
@@ -445,7 +450,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
anim.addUpdateListener(mAnimatorUpdateListener);
anim.setStartDelay(startDelay);
anim.setDuration(duration);
- anim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ anim.setInterpolator(InterpolatorsAndroidX.LINEAR_OUT_SLOW_IN);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -479,6 +484,10 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
* (1.0f - mKeyguardHeadsUpShowingAmount);
}
+ if (mSystemEventAnimator.isAnimationRunning()) {
+ newAlpha = Math.min(newAlpha, mSystemEventAnimatorAlpha);
+ }
+
boolean hideForBypass =
mFirstBypassAttempt && mKeyguardUpdateMonitor.shouldListenForFace()
|| mDelayShowingKeyguardStatusBar;
@@ -487,7 +496,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
&& !mDozing
&& !hideForBypass
&& !mDisableStateTracker.isDisabled()
- ? View.VISIBLE : View.INVISIBLE;
+ ? View.VISIBLE : View.INVISIBLE;
updateViewState(newAlpha, newVisibility);
}
@@ -613,4 +622,15 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
updateBlockedIcons();
}
};
+
+ private StatusBarSystemEventDefaultAnimator getSystemEventAnimator(boolean isAnimationRunning) {
+ return new StatusBarSystemEventDefaultAnimator(getResources(), (alpha) -> {
+ mSystemEventAnimatorAlpha = alpha;
+ updateViewState();
+ return Unit.INSTANCE;
+ }, (translationX) -> {
+ mView.setTranslationX(translationX);
+ return Unit.INSTANCE;
+ }, isAnimationRunning);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 6c532a5c5fab..e6b76ad0e00c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -22,8 +22,6 @@ import android.annotation.Nullable;
import android.app.ActivityTaskManager;
import android.app.AlarmManager;
import android.app.AlarmManager.AlarmClockInfo;
-import android.app.IActivityManager;
-import android.app.SynchronousUserSwitchObserver;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -134,7 +132,6 @@ public class PhoneStatusBarPolicy
private final NextAlarmController mNextAlarmController;
private final AlarmManager mAlarmManager;
private final UserInfoController mUserInfoController;
- private final IActivityManager mIActivityManager;
private final UserManager mUserManager;
private final UserTracker mUserTracker;
private final DevicePolicyManager mDevicePolicyManager;
@@ -149,6 +146,7 @@ public class PhoneStatusBarPolicy
private final KeyguardStateController mKeyguardStateController;
private final LocationController mLocationController;
private final PrivacyItemController mPrivacyItemController;
+ private final Executor mMainExecutor;
private final Executor mUiBgExecutor;
private final SensorPrivacyController mSensorPrivacyController;
private final RecordingController mRecordingController;
@@ -168,16 +166,17 @@ public class PhoneStatusBarPolicy
@Inject
public PhoneStatusBarPolicy(StatusBarIconController iconController,
CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher,
- @UiBackground Executor uiBgExecutor, @Main Looper looper, @Main Resources resources,
- CastController castController, HotspotController hotspotController,
- BluetoothController bluetoothController, NextAlarmController nextAlarmController,
- UserInfoController userInfoController, RotationLockController rotationLockController,
- DataSaverController dataSaverController, ZenModeController zenModeController,
+ @Main Executor mainExecutor, @UiBackground Executor uiBgExecutor, @Main Looper looper,
+ @Main Resources resources, CastController castController,
+ HotspotController hotspotController, BluetoothController bluetoothController,
+ NextAlarmController nextAlarmController, UserInfoController userInfoController,
+ RotationLockController rotationLockController, DataSaverController dataSaverController,
+ ZenModeController zenModeController,
DeviceProvisionedController deviceProvisionedController,
KeyguardStateController keyguardStateController,
LocationController locationController,
- SensorPrivacyController sensorPrivacyController, IActivityManager iActivityManager,
- AlarmManager alarmManager, UserManager userManager, UserTracker userTracker,
+ SensorPrivacyController sensorPrivacyController, AlarmManager alarmManager,
+ UserManager userManager, UserTracker userTracker,
DevicePolicyManager devicePolicyManager, RecordingController recordingController,
@Nullable TelecomManager telecomManager, @DisplayId int displayId,
@Main SharedPreferences sharedPreferences, DateFormatUtil dateFormatUtil,
@@ -195,7 +194,6 @@ public class PhoneStatusBarPolicy
mNextAlarmController = nextAlarmController;
mAlarmManager = alarmManager;
mUserInfoController = userInfoController;
- mIActivityManager = iActivityManager;
mUserManager = userManager;
mUserTracker = userTracker;
mDevicePolicyManager = devicePolicyManager;
@@ -208,6 +206,7 @@ public class PhoneStatusBarPolicy
mPrivacyItemController = privacyItemController;
mSensorPrivacyController = sensorPrivacyController;
mRecordingController = recordingController;
+ mMainExecutor = mainExecutor;
mUiBgExecutor = uiBgExecutor;
mTelecomManager = telecomManager;
mRingerModeTracker = ringerModeTracker;
@@ -256,11 +255,7 @@ public class PhoneStatusBarPolicy
mRingerModeTracker.getRingerModeInternal().observeForever(observer);
// listen for user / profile change.
- try {
- mIActivityManager.registerUserSwitchObserver(mUserSwitchListener, TAG);
- } catch (RemoteException e) {
- // Ignore
- }
+ mUserTracker.addCallback(mUserSwitchListener, mMainExecutor);
// TTY status
updateTTY();
@@ -555,15 +550,15 @@ public class PhoneStatusBarPolicy
});
}
- private final SynchronousUserSwitchObserver mUserSwitchListener =
- new SynchronousUserSwitchObserver() {
+ private final UserTracker.Callback mUserSwitchListener =
+ new UserTracker.Callback() {
@Override
- public void onUserSwitching(int newUserId) throws RemoteException {
+ public void onUserChanging(int newUser, Context userContext) {
mHandler.post(() -> mUserInfoController.reloadUserInfo());
}
@Override
- public void onUserSwitchComplete(int newUserId) throws RemoteException {
+ public void onUserChanged(int newUser, Context userContext) {
mHandler.post(() -> {
updateAlarm();
updateManagedProfile();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 28bc64de2cb9..d546a84791fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -35,6 +35,7 @@ import android.widget.LinearLayout;
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dependency;
+import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
@@ -60,7 +61,7 @@ public class PhoneStatusBarView extends FrameLayout {
private Rect mDisplaySize;
private int mStatusBarHeight;
@Nullable
- private TouchEventHandler mTouchEventHandler;
+ private Gefingerpoken mTouchEventHandler;
/**
* Draw this many pixels into the left/right side of the cutout to optimally use the space
@@ -72,7 +73,7 @@ public class PhoneStatusBarView extends FrameLayout {
mContentInsetsProvider = Dependency.get(StatusBarContentInsetsProvider.class);
}
- void setTouchEventHandler(TouchEventHandler handler) {
+ void setTouchEventHandler(Gefingerpoken handler) {
mTouchEventHandler = handler;
}
@@ -185,7 +186,7 @@ public class PhoneStatusBarView extends FrameLayout {
);
return true;
}
- return mTouchEventHandler.handleTouchEvent(event);
+ return mTouchEventHandler.onTouchEvent(event);
}
@Override
@@ -267,28 +268,4 @@ public class PhoneStatusBarView extends FrameLayout {
insets.second,
getPaddingBottom());
}
-
- /**
- * A handler responsible for all touch event handling on the status bar.
- *
- * Touches that occur on the status bar view may have ramifications for the notification
- * panel (e.g. a touch that pulls down the shade could start on the status bar), so this
- * interface provides a way to notify the panel controller when these touches occur.
- *
- * The handler will be notified each time {@link PhoneStatusBarView#onTouchEvent} and
- * {@link PhoneStatusBarView#onInterceptTouchEvent} are called.
- **/
- public interface TouchEventHandler {
- /** Called each time {@link PhoneStatusBarView#onInterceptTouchEvent} is called. */
- void onInterceptTouchEvent(MotionEvent event);
-
- /**
- * Called each time {@link PhoneStatusBarView#onTouchEvent} is called.
- *
- * Should return true if the touch was handled by this handler and false otherwise. The
- * return value from the handler will be returned from
- * {@link PhoneStatusBarView#onTouchEvent}.
- */
- boolean handleTouchEvent(MotionEvent event);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index 11bc490286f9..9a5d1b5514f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -24,11 +24,11 @@ import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
+import com.android.systemui.Gefingerpoken
import com.android.systemui.R
import com.android.systemui.shade.ShadeController
import com.android.systemui.shade.ShadeLogger
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
-import com.android.systemui.statusbar.phone.PhoneStatusBarView.TouchEventHandler
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.unfold.SysUIUnfoldComponent
import com.android.systemui.unfold.UNFOLD_STATUS_BAR
@@ -131,7 +131,7 @@ class PhoneStatusBarViewController private constructor(
}
/** Called when a touch event occurred on {@link PhoneStatusBarView}. */
- fun onTouchEvent(event: MotionEvent) {
+ fun onTouch(event: MotionEvent) {
if (centralSurfaces.statusBarWindowState == WINDOW_STATE_SHOWING) {
val upOrCancel =
event.action == MotionEvent.ACTION_UP ||
@@ -141,13 +141,14 @@ class PhoneStatusBarViewController private constructor(
}
}
- inner class PhoneStatusBarViewTouchHandler : TouchEventHandler {
- override fun onInterceptTouchEvent(event: MotionEvent) {
- onTouchEvent(event)
+ inner class PhoneStatusBarViewTouchHandler : Gefingerpoken {
+ override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
+ onTouch(event)
+ return false
}
- override fun handleTouchEvent(event: MotionEvent): Boolean {
- onTouchEvent(event)
+ override fun onTouchEvent(event: MotionEvent): Boolean {
+ onTouch(event)
// If panels aren't enabled, ignore the gesture and don't pass it down to the
// panel view.
@@ -174,7 +175,7 @@ class PhoneStatusBarViewController private constructor(
return true
}
}
- return centralSurfaces.notificationPanelViewController.sendTouchEventToView(event)
+ return centralSurfaces.notificationPanelViewController.handleExternalTouch(event)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 80093a3da325..f5d2eee35c93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
+
import static java.lang.Float.isNaN;
import android.animation.Animator;
@@ -52,10 +54,18 @@ import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
+import com.android.systemui.keyguard.shared.model.ScrimAlpha;
+import com.android.systemui.keyguard.shared.model.TransitionState;
+import com.android.systemui.keyguard.shared.model.TransitionStep;
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
import com.android.systemui.scrim.ScrimView;
import com.android.systemui.shade.NotificationPanelViewController;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.notification.stack.ViewState;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -71,6 +81,8 @@ import java.util.function.Consumer;
import javax.inject.Inject;
+import kotlinx.coroutines.CoroutineDispatcher;
+
/**
* Controls both the scrim behind the notifications and in front of the notifications (when a
* security method gets shown).
@@ -138,26 +150,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
private boolean mTransitioningToFullShade;
/**
- * Is there currently an unocclusion animation running. Used to avoid bright flickers
- * of the notification scrim.
- */
- private boolean mUnOcclusionAnimationRunning;
-
- /**
* The percentage of the bouncer which is hidden. If 1, the bouncer is completely hidden. If
* 0, the bouncer is visible.
*/
@FloatRange(from = 0, to = 1)
private float mBouncerHiddenFraction = KeyguardBouncerConstants.EXPANSION_HIDDEN;
- /**
- * Set whether an unocclusion animation is currently running on the notification panel. Used
- * to avoid bright flickers of the notification scrim.
- */
- public void setUnocclusionAnimationRunning(boolean unocclusionAnimationRunning) {
- mUnOcclusionAnimationRunning = unocclusionAnimationRunning;
- }
-
@IntDef(prefix = {"VISIBILITY_"}, value = {
TRANSPARENT,
SEMI_TRANSPARENT,
@@ -249,6 +247,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
private boolean mWallpaperVisibilityTimedOut;
private int mScrimsVisibility;
private final TriConsumer<ScrimState, Float, GradientColors> mScrimStateListener;
+ private final LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
+ private final FeatureFlags mFeatureFlags;
private Consumer<Integer> mScrimVisibleListener;
private boolean mBlankScreen;
private boolean mScreenBlankingCallbackCalled;
@@ -265,6 +265,24 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
private boolean mWakeLockHeld;
private boolean mKeyguardOccluded;
+ private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+ private CoroutineDispatcher mMainDispatcher;
+ private boolean mIsBouncerToGoneTransitionRunning = false;
+ private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
+ private final Consumer<ScrimAlpha> mScrimAlphaConsumer =
+ (ScrimAlpha alphas) -> {
+ mInFrontAlpha = alphas.getFrontAlpha();
+ mScrimInFront.setViewAlpha(mInFrontAlpha);
+
+ mNotificationsAlpha = alphas.getNotificationsAlpha();
+ mNotificationsScrim.setViewAlpha(mNotificationsAlpha);
+
+ mBehindAlpha = alphas.getBehindAlpha();
+ mScrimBehind.setViewAlpha(mBehindAlpha);
+ };
+
+ Consumer<TransitionStep> mPrimaryBouncerToGoneTransition;
+
@Inject
public ScrimController(
LightBarController lightBarController,
@@ -279,8 +297,15 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
@Main Executor mainExecutor,
ScreenOffAnimationController screenOffAnimationController,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
- StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+ PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
+ KeyguardTransitionInteractor keyguardTransitionInteractor,
+ @Main CoroutineDispatcher mainDispatcher,
+ LargeScreenShadeInterpolator largeScreenShadeInterpolator,
+ FeatureFlags featureFlags) {
mScrimStateListener = lightBarController::setScrimState;
+ mLargeScreenShadeInterpolator = largeScreenShadeInterpolator;
+ mFeatureFlags = featureFlags;
mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
mKeyguardStateController = keyguardStateController;
@@ -318,6 +343,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
}
});
mColors = new GradientColors();
+ mPrimaryBouncerToGoneTransitionViewModel = primaryBouncerToGoneTransitionViewModel;
+ mKeyguardTransitionInteractor = keyguardTransitionInteractor;
+ mMainDispatcher = mainDispatcher;
}
/**
@@ -357,6 +385,33 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
for (ScrimState state : ScrimState.values()) {
state.prepare(state);
}
+
+ // Directly control transition to UNLOCKED scrim state from PRIMARY_BOUNCER, and make sure
+ // to report back that keyguard has faded away. This fixes cases where the scrim state was
+ // rapidly switching on unlock, due to shifts in state in CentralSurfacesImpl
+ mPrimaryBouncerToGoneTransition =
+ (TransitionStep step) -> {
+ TransitionState state = step.getTransitionState();
+
+ mIsBouncerToGoneTransitionRunning = state == TransitionState.RUNNING;
+
+ if (state == TransitionState.STARTED) {
+ setExpansionAffectsAlpha(false);
+ transitionTo(ScrimState.UNLOCKED);
+ }
+
+ if (state == TransitionState.FINISHED || state == TransitionState.CANCELED) {
+ setExpansionAffectsAlpha(true);
+ if (mKeyguardStateController.isKeyguardFadingAway()) {
+ mStatusBarKeyguardViewManager.onKeyguardFadedAway();
+ }
+ }
+ };
+
+ collectFlow(behindScrim, mKeyguardTransitionInteractor.getPrimaryBouncerToGoneTransition(),
+ mPrimaryBouncerToGoneTransition, mMainDispatcher);
+ collectFlow(behindScrim, mPrimaryBouncerToGoneTransitionViewModel.getScrimAlpha(),
+ mScrimAlphaConsumer, mMainDispatcher);
}
/**
@@ -379,6 +434,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
}
public void transitionTo(ScrimState state, Callback callback) {
+ if (mIsBouncerToGoneTransitionRunning) {
+ Log.i(TAG, "Skipping transition to: " + state
+ + " while mIsBouncerToGoneTransitionRunning");
+ return;
+ }
if (state == mState) {
// Call the callback anyway, unless it's already enqueued
if (callback != null && mCallback != callback) {
@@ -532,10 +592,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
}
}
- public void onExpandingFinished() {
- setUnocclusionAnimationRunning(false);
- }
-
@VisibleForTesting
protected void onHideWallpaperTimeout() {
if (mState != ScrimState.AOD && mState != ScrimState.PULSING) {
@@ -791,16 +847,21 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
if (!mScreenOffAnimationController.shouldExpandNotifications()
&& !mAnimatingPanelExpansionOnUnlock
&& !occluding) {
- if (mClipsQsScrim) {
+ if (mTransparentScrimBackground) {
+ mBehindAlpha = 0;
+ mNotificationsAlpha = 0;
+ } else if (mClipsQsScrim) {
float behindFraction = getInterpolatedFraction();
behindFraction = (float) Math.pow(behindFraction, 0.8f);
- mBehindAlpha = mTransparentScrimBackground ? 0 : 1;
- mNotificationsAlpha =
- mTransparentScrimBackground ? 0 : behindFraction * mDefaultScrimAlpha;
+ mBehindAlpha = 1;
+ mNotificationsAlpha = behindFraction * mDefaultScrimAlpha;
} else {
- if (mTransparentScrimBackground) {
- mBehindAlpha = 0;
- mNotificationsAlpha = 0;
+ if (mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+ mBehindAlpha = mLargeScreenShadeInterpolator.getBehindScrimAlpha(
+ mPanelExpansionFraction * mDefaultScrimAlpha);
+ mNotificationsAlpha =
+ mLargeScreenShadeInterpolator.getNotificationScrimAlpha(
+ mPanelExpansionFraction);
} else {
// Behind scrim will finish fading in at 30% expansion.
float behindFraction = MathUtils
@@ -875,13 +936,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
if (mKeyguardOccluded || hideNotificationScrim) {
mNotificationsAlpha = 0;
}
- if (mUnOcclusionAnimationRunning && mState == ScrimState.KEYGUARD) {
- // We're unoccluding the keyguard and don't want to have a bright flash.
- mNotificationsAlpha = ScrimState.KEYGUARD.getNotifAlpha();
- mNotificationsTint = ScrimState.KEYGUARD.getNotifTint();
- mBehindAlpha = ScrimState.KEYGUARD.getBehindAlpha();
- mBehindTint = ScrimState.KEYGUARD.getBehindTint();
- }
}
if (mState != ScrimState.UNLOCKED) {
mAnimatingPanelExpansionOnUnlock = false;
@@ -1150,7 +1204,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_tint",
Color.alpha(tint));
scrimView.setTint(tint);
- scrimView.setViewAlpha(alpha);
+ if (!mIsBouncerToGoneTransitionRunning) {
+ scrimView.setViewAlpha(alpha);
+ }
} else {
scrim.setAlpha(alpha);
}
@@ -1498,6 +1554,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
}
public void setKeyguardOccluded(boolean keyguardOccluded) {
+ if (mKeyguardOccluded == keyguardOccluded) {
+ return;
+ }
mKeyguardOccluded = keyguardOccluded;
updateScrims();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 11863627218e..04cc8ce792d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -569,7 +569,10 @@ public interface StatusBarIconController {
mGroup.addView(view, index, onCreateLayoutParams());
if (mIsInDemoMode) {
- mDemoStatusIcons.addModernMobileView(mContext, subId);
+ mDemoStatusIcons.addModernMobileView(
+ mContext,
+ mMobileIconsViewModel.getLogger(),
+ subId);
}
return view;
@@ -601,6 +604,7 @@ public interface StatusBarIconController {
return ModernStatusBarMobileView
.constructAndBind(
mobileContext,
+ mMobileIconsViewModel.getLogger(),
slot,
mMobileIconsViewModel.viewModelForSub(subId, mLocation)
);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
index f6c0da8da8c0..833cb93f62e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
@@ -79,6 +79,18 @@ public class StatusBarIconHolder {
private @IconType int mType = TYPE_ICON;
private int mTag = 0;
+ /** Returns a human-readable string representing the given type. */
+ public static String getTypeString(@IconType int type) {
+ switch(type) {
+ case TYPE_ICON: return "ICON";
+ case TYPE_WIFI: return "WIFI_OLD";
+ case TYPE_MOBILE: return "MOBILE_OLD";
+ case TYPE_MOBILE_NEW: return "MOBILE_NEW";
+ case TYPE_WIFI_NEW: return "WIFI_NEW";
+ default: return "UNKNOWN";
+ }
+ }
+
private StatusBarIconHolder() {
}
@@ -230,4 +242,11 @@ public class StatusBarIconHolder {
public int getTag() {
return mTag;
}
+
+ @Override
+ public String toString() {
+ return "StatusBarIconHolder(type=" + getTypeString(mType)
+ + " tag=" + getTag()
+ + " visible=" + isVisible() + ")";
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
index 8800b05fadb7..565481a20d95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
@@ -27,6 +27,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
/** A class holding the list of all the system icons that could be shown in the status bar. */
public class StatusBarIconList {
@@ -302,7 +303,7 @@ public class StatusBarIconList {
@Override
public String toString() {
- return String.format("(%s) %s", mName, subSlotsString());
+ return String.format("(%s) holder=%s %s", mName, mHolder, subSlotsString());
}
private String subSlotsString() {
@@ -310,7 +311,10 @@ public class StatusBarIconList {
return "";
}
- return "" + mSubSlots.size() + " subSlots";
+ return "| " + mSubSlots.size() + " subSlots: "
+ + mSubSlots.stream()
+ .map(StatusBarIconHolder::toString)
+ .collect(Collectors.joining("|"));
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 39281da09749..bea779336b36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -66,6 +66,7 @@ import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInt
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.navigationbar.TaskbarDelegate;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.ShadeController;
@@ -279,7 +280,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private boolean mLastScreenOffAnimationPlaying;
private float mQsExpansion;
final Set<KeyguardViewManagerCallback> mCallbacks = new HashSet<>();
- private boolean mIsUnoccludeTransitionFlagEnabled;
private boolean mIsModernAlternateBouncerEnabled;
private boolean mIsBackAnimationEnabled;
@@ -300,6 +300,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Nullable private KeyguardBypassController mBypassController;
@Nullable private OccludingAppBiometricUI mOccludingAppBiometricUI;
+ @Nullable private TaskbarDelegate mTaskbarDelegate;
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -357,7 +358,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mPrimaryBouncerView = primaryBouncerView;
mFoldAodAnimationController = sysUIUnfoldComponent
.map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
- mIsUnoccludeTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
mIsModernAlternateBouncerEnabled = featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER);
mAlternateBouncerInteractor = alternateBouncerInteractor;
mIsBackAnimationEnabled =
@@ -405,14 +405,14 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
/**
- * Sets a new legacy alternate bouncer. Only used if mdoern alternate bouncer is NOT enable.
+ * Sets a new legacy alternate bouncer. Only used if modern alternate bouncer is NOT enabled.
*/
public void setLegacyAlternateBouncer(@NonNull LegacyAlternateBouncer alternateBouncerLegacy) {
if (!mIsModernAlternateBouncerEnabled) {
if (!Objects.equals(mAlternateBouncerInteractor.getLegacyAlternateBouncer(),
alternateBouncerLegacy)) {
mAlternateBouncerInteractor.setLegacyAlternateBouncer(alternateBouncerLegacy);
- hideAlternateBouncer(false);
+ hideAlternateBouncer(true);
}
}
@@ -564,6 +564,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
updateStates();
}
+ public void setTaskbarDelegate(TaskbarDelegate taskbarDelegate) {
+ mTaskbarDelegate = taskbarDelegate;
+ }
+
/**
* Show the keyguard. Will handle creating and attaching to the view manager
* lazily.
@@ -636,8 +640,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
*/
public void showPrimaryBouncer(boolean scrimmed) {
hideAlternateBouncer(false);
-
- if (mKeyguardStateController.isShowing() && !isBouncerShowing()) {
+ if (mKeyguardStateController.isShowing() && !isBouncerShowing()) {
mPrimaryBouncerInteractor.show(scrimmed);
}
updateStates();
@@ -729,15 +732,17 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
} else {
showBouncerOrKeyguard(hideBouncerWhenShowing);
}
- hideAlternateBouncer(false);
+ if (hideBouncerWhenShowing) {
+ hideAlternateBouncer(true);
+ }
mKeyguardUpdateManager.sendKeyguardReset();
updateStates();
}
}
@Override
- public void hideAlternateBouncer(boolean forceUpdateScrim) {
- updateAlternateBouncerShowing(mAlternateBouncerInteractor.hide() || forceUpdateScrim);
+ public void hideAlternateBouncer(boolean updateScrim) {
+ updateAlternateBouncerShowing(mAlternateBouncerInteractor.hide() && updateScrim);
}
private void updateAlternateBouncerShowing(boolean updateScrim) {
@@ -790,7 +795,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Override
public void onFinishedGoingToSleep() {
- mPrimaryBouncerInteractor.onScreenTurnedOff();
+ mPrimaryBouncerInteractor.hide();
}
@Override
@@ -874,11 +879,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
// by a FLAG_DISMISS_KEYGUARD_ACTIVITY.
reset(isOccluding /* hideBouncerWhenShowing*/);
}
- if (!mIsUnoccludeTransitionFlagEnabled) {
- if (animate && !isOccluded && isShowing && !primaryBouncerIsShowing()) {
- mCentralSurfaces.animateKeyguardUnoccluding();
- }
- }
}
@Override
@@ -1194,7 +1194,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
* Updates the visibility of the nav bar window (which will cause insets changes).
*/
protected void updateNavigationBarVisibility(boolean navBarVisible) {
- if (mCentralSurfaces.getNavigationBarView() != null) {
+ if (mCentralSurfaces.getNavigationBarView() != null
+ || (mTaskbarDelegate != null && mTaskbarDelegate.isInitialized())) {
if (navBarVisible) {
long delay = getNavBarShowDelay();
if (delay == 0) {
@@ -1446,16 +1447,21 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
* For any touches on the NPVC, show the primary bouncer if the alternate bouncer is currently
* showing.
*/
- public void onTouch(MotionEvent event) {
- if (mAlternateBouncerInteractor.isVisibleState()
+ public boolean onTouch(MotionEvent event) {
+ boolean handledTouch = false;
+ if (event.getAction() == MotionEvent.ACTION_UP
+ && mAlternateBouncerInteractor.isVisibleState()
&& mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()) {
showPrimaryBouncer(true);
+ handledTouch = true;
}
// Forward NPVC touches to callbacks in case they want to respond to touches
for (KeyguardViewManagerCallback callback: mCallbacks) {
callback.onTouch(event);
}
+
+ return handledTouch;
}
/** Update keyguard position based on a tapped X coordinate. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
index 79c0984d9bf7..d30d0e25bd8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
@@ -22,6 +22,7 @@ import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator.AlphaP
import com.android.systemui.statusbar.phone.PhoneStatusBarViewController.StatusBarViewsCenterProvider
import com.android.systemui.unfold.SysUIUnfoldScope
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.unfold.util.CurrentActivityTypeProvider
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
import javax.inject.Inject
import kotlin.math.max
@@ -29,9 +30,13 @@ import kotlin.math.max
@SysUIUnfoldScope
class StatusBarMoveFromCenterAnimationController @Inject constructor(
private val progressProvider: ScopedUnfoldTransitionProgressProvider,
+ private val currentActivityTypeProvider: CurrentActivityTypeProvider,
windowManager: WindowManager
) {
+ // Whether we're on home activity. Updated only when the animation starts.
+ private var isOnHomeActivity: Boolean? = null
+
private val transitionListener = TransitionListener()
private val moveFromCenterAnimator = UnfoldMoveFromCenterAnimator(
windowManager,
@@ -60,6 +65,10 @@ class StatusBarMoveFromCenterAnimationController @Inject constructor(
}
private inner class TransitionListener : TransitionProgressListener {
+ override fun onTransitionStarted() {
+ isOnHomeActivity = currentActivityTypeProvider.isHomeActivity
+ }
+
override fun onTransitionProgress(progress: Float) {
moveFromCenterAnimator.onTransitionProgress(progress)
}
@@ -68,11 +77,23 @@ class StatusBarMoveFromCenterAnimationController @Inject constructor(
// Reset translations when transition is stopped/cancelled
// (e.g. the transition could be cancelled mid-way when rotating the screen)
moveFromCenterAnimator.onTransitionProgress(1f)
+ isOnHomeActivity = null
}
}
- private class StatusBarIconsAlphaProvider : AlphaProvider {
+
+ /**
+ * In certain cases, an alpha is applied based on the progress.
+ *
+ * This mainly happens to hide the statusbar during the unfold animation while on apps, as the
+ * bounds of the app "collapse" to the center, but the statusbar doesn't.
+ * While on launcher, this alpha is not applied.
+ */
+ private inner class StatusBarIconsAlphaProvider : AlphaProvider {
override fun getAlpha(progress: Float): Float {
+ if (isOnHomeActivity == true) {
+ return 1.0f
+ }
return max(
0f,
(progress - ICONS_START_APPEARING_PROGRESS) / (1 - ICONS_START_APPEARING_PROGRESS)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 078a00d33493..189f2e3098fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -27,6 +27,7 @@ import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ResolveInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
@@ -45,6 +46,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.EventLogTags;
@@ -74,6 +76,7 @@ import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.wmshell.BubblesManager;
+import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -81,6 +84,7 @@ import javax.inject.Inject;
import dagger.Lazy;
+
/**
* Status bar implementation of {@link NotificationActivityStarter}.
*/
@@ -572,16 +576,29 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
});
// not immersive & a fullscreen alert should be shown
- final PendingIntent fullscreenIntent =
+ final PendingIntent fullScreenIntent =
entry.getSbn().getNotification().fullScreenIntent;
- mLogger.logSendingFullScreenIntent(entry, fullscreenIntent);
+ mLogger.logSendingFullScreenIntent(entry, fullScreenIntent);
try {
EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
entry.getKey());
mCentralSurfaces.wakeUpForFullScreenIntent();
- fullscreenIntent.send();
+ fullScreenIntent.send();
entry.notifyFullScreenIntentLaunched();
mMetricsLogger.count("note_fullscreen", 1);
+
+ String activityName;
+ List<ResolveInfo> resolveInfos = fullScreenIntent.queryIntentComponents(0);
+ if (resolveInfos.size() > 0 && resolveInfos.get(0) != null
+ && resolveInfos.get(0).activityInfo != null
+ && resolveInfos.get(0).activityInfo.name != null) {
+ activityName = resolveInfos.get(0).activityInfo.name;
+ } else {
+ activityName = "";
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.FULL_SCREEN_INTENT_LAUNCHED,
+ fullScreenIntent.getCreatorUid(),
+ activityName);
} catch (PendingIntent.CanceledException e) {
// ignore
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
index aec196fc90f0..8e59a8b62a05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
@@ -22,11 +22,11 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
import com.android.keyguard.LockIconViewController;
import com.android.systemui.biometrics.AuthRippleController;
-import com.android.systemui.shade.LargeScreenShadeHeaderController;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.NotificationShadeWindowViewController;
import com.android.systemui.shade.QuickSettingsController;
+import com.android.systemui.shade.ShadeHeaderController;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.core.StatusBarInitializer;
@@ -138,9 +138,9 @@ public interface CentralSurfacesComponent {
CentralSurfacesCommandQueueCallbacks getCentralSurfacesCommandQueueCallbacks();
/**
- * Creates a {@link LargeScreenShadeHeaderController}.
+ * Creates a {@link ShadeHeaderController}.
*/
- LargeScreenShadeHeaderController getLargeScreenShadeHeaderController();
+ ShadeHeaderController getLargeScreenShadeHeaderController();
/**
* Creates a new {@link CollapsedStatusBarFragment} each time it's called. See
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
index c1c6c88da822..0929233feb88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
@@ -20,9 +20,10 @@ import android.annotation.Nullable;
import android.content.ContentResolver;
import android.os.Handler;
import android.view.LayoutInflater;
-import android.view.View;
import android.view.ViewStub;
+import androidx.constraintlayout.motion.widget.MotionLayout;
+
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.LockIconView;
import com.android.systemui.R;
@@ -32,7 +33,6 @@ import com.android.systemui.biometrics.AuthRippleView;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.privacy.OngoingPrivacyChip;
import com.android.systemui.settings.UserTracker;
@@ -85,9 +85,7 @@ import dagger.multibindings.IntoSet;
@Module(subcomponents = StatusBarFragmentComponent.class)
public abstract class StatusBarViewModule {
- public static final String LARGE_SCREEN_SHADE_HEADER = "large_screen_shade_header";
- private static final String SPLIT_SHADE_BATTERY_VIEW = "split_shade_battery_view";
- public static final String LARGE_SCREEN_BATTERY_CONTROLLER = "split_shade_battery_controller";
+ public static final String SHADE_HEADER = "large_screen_shade_header";
public static final String STATUS_BAR_FRAGMENT = "status_bar_fragment";
/** */
@@ -171,17 +169,15 @@ public abstract class StatusBarViewModule {
/** */
@Provides
- @Named(LARGE_SCREEN_SHADE_HEADER)
+ @Named(SHADE_HEADER)
@CentralSurfacesComponent.CentralSurfacesScope
- public static View getLargeScreenShadeHeaderBarView(
+ public static MotionLayout getLargeScreenShadeHeaderBarView(
NotificationShadeWindowView notificationShadeWindowView,
FeatureFlags featureFlags) {
ViewStub stub = notificationShadeWindowView.findViewById(R.id.qs_header_stub);
- int layoutId = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)
- ? R.layout.combined_qs_header
- : R.layout.large_screen_shade_header;
+ int layoutId = R.layout.combined_qs_header;
stub.setLayoutResource(layoutId);
- View v = stub.inflate();
+ MotionLayout v = (MotionLayout) stub.inflate();
return v;
}
@@ -197,7 +193,7 @@ public abstract class StatusBarViewModule {
@Provides
@CentralSurfacesComponent.CentralSurfacesScope
public static OngoingPrivacyChip getSplitShadeOngoingPrivacyChip(
- @Named(LARGE_SCREEN_SHADE_HEADER) View header) {
+ @Named(SHADE_HEADER) MotionLayout header) {
return header.findViewById(R.id.privacy_chip);
}
@@ -205,23 +201,23 @@ public abstract class StatusBarViewModule {
@Provides
@CentralSurfacesComponent.CentralSurfacesScope
static StatusIconContainer providesStatusIconContainer(
- @Named(LARGE_SCREEN_SHADE_HEADER) View header) {
+ @Named(SHADE_HEADER) MotionLayout header) {
return header.findViewById(R.id.statusIcons);
}
/** */
@Provides
@CentralSurfacesComponent.CentralSurfacesScope
- @Named(SPLIT_SHADE_BATTERY_VIEW)
- static BatteryMeterView getBatteryMeterView(@Named(LARGE_SCREEN_SHADE_HEADER) View view) {
+ @Named(SHADE_HEADER)
+ static BatteryMeterView getBatteryMeterView(@Named(SHADE_HEADER) MotionLayout view) {
return view.findViewById(R.id.batteryRemainingIcon);
}
@Provides
@CentralSurfacesComponent.CentralSurfacesScope
- @Named(LARGE_SCREEN_BATTERY_CONTROLLER)
+ @Named(SHADE_HEADER)
static BatteryMeterViewController getBatteryMeterViewController(
- @Named(SPLIT_SHADE_BATTERY_VIEW) BatteryMeterView batteryMeterView,
+ @Named(SHADE_HEADER) BatteryMeterView batteryMeterView,
UserTracker userTracker,
ConfigurationController configurationController,
TunerService tunerService,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 00fd4ef9a1fc..2fe714533f5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -23,7 +23,6 @@ import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.IDLE;
import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.SHOWING_PERSISTENT_DOT;
-import android.animation.Animator;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.Fragment;
@@ -43,6 +42,7 @@ import android.view.ViewStub;
import android.widget.LinearLayout;
import androidx.annotation.VisibleForTesting;
+import androidx.core.animation.Animator;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dumpable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
index fe69f7507503..5903fa3d5bd1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
@@ -16,9 +16,9 @@
package com.android.systemui.statusbar.phone.fragment
-import android.animation.Animator
-import android.animation.AnimatorSet
-import android.animation.ValueAnimator
+import androidx.core.animation.Animator
+import androidx.core.animation.AnimatorSet
+import androidx.core.animation.ValueAnimator
import android.content.res.Resources
import android.view.View
import com.android.systemui.R
@@ -26,19 +26,39 @@ import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_IN
import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_OUT
import com.android.systemui.statusbar.events.SystemStatusAnimationCallback
import com.android.systemui.util.animation.AnimationUtil.Companion.frames
+import com.android.systemui.util.doOnCancel
+import com.android.systemui.util.doOnEnd
+
+/**
+ * An implementation of [StatusBarSystemEventDefaultAnimator], applying the onAlphaChanged and
+ * onTranslationXChanged callbacks directly to the provided animatedView.
+ */
+class StatusBarSystemEventAnimator @JvmOverloads constructor(
+ val animatedView: View,
+ resources: Resources,
+ isAnimationRunning: Boolean = false
+) : StatusBarSystemEventDefaultAnimator(
+ resources = resources,
+ onAlphaChanged = animatedView::setAlpha,
+ onTranslationXChanged = animatedView::setTranslationX,
+ isAnimationRunning = isAnimationRunning
+)
/**
* Tied directly to [SystemStatusAnimationScheduler]. Any StatusBar-like thing (keyguard, collapsed
- * status bar fragment), can just feed this an animatable view to get the default system status
- * animation.
+ * status bar fragment), can use this Animator to get the default system status animation. It simply
+ * needs to implement the onAlphaChanged and onTranslationXChanged callbacks.
*
* This animator relies on resources, and should be recreated whenever resources are updated. While
* this class could be used directly as the animation callback, it's probably best to forward calls
* to it so that it can be recreated at any moment without needing to remove/add callback.
*/
-class StatusBarSystemEventAnimator(
- val animatedView: View,
- resources: Resources
+
+open class StatusBarSystemEventDefaultAnimator @JvmOverloads constructor(
+ resources: Resources,
+ private val onAlphaChanged: (Float) -> Unit,
+ private val onTranslationXChanged: (Float) -> Unit,
+ var isAnimationRunning: Boolean = false
) : SystemStatusAnimationCallback {
private val translationXIn: Int = resources.getDimensionPixelSize(
R.dimen.ongoing_appops_chip_animation_in_status_bar_translation_x)
@@ -46,15 +66,20 @@ class StatusBarSystemEventAnimator(
R.dimen.ongoing_appops_chip_animation_out_status_bar_translation_x)
override fun onSystemEventAnimationBegin(): Animator {
- val moveOut = ValueAnimator.ofFloat(0f, 1f).setDuration(23.frames)
- moveOut.interpolator = STATUS_BAR_X_MOVE_OUT
- moveOut.addUpdateListener { animation: ValueAnimator ->
- animatedView.translationX = -(translationXIn * animation.animatedValue as Float)
+ isAnimationRunning = true
+ val moveOut = ValueAnimator.ofFloat(0f, 1f).apply {
+ duration = 23.frames
+ interpolator = STATUS_BAR_X_MOVE_OUT
+ addUpdateListener {
+ onTranslationXChanged(-(translationXIn * animatedValue as Float))
+ }
}
- val alphaOut = ValueAnimator.ofFloat(1f, 0f).setDuration(8.frames)
- alphaOut.interpolator = null
- alphaOut.addUpdateListener { animation: ValueAnimator ->
- animatedView.alpha = animation.animatedValue as Float
+ val alphaOut = ValueAnimator.ofFloat(1f, 0f).apply {
+ duration = 8.frames
+ interpolator = null
+ addUpdateListener {
+ onAlphaChanged(animatedValue as Float)
+ }
}
val animSet = AnimatorSet()
@@ -63,23 +88,28 @@ class StatusBarSystemEventAnimator(
}
override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator {
- animatedView.translationX = translationXOut.toFloat()
- val moveIn = ValueAnimator.ofFloat(1f, 0f).setDuration(28.frames)
- moveIn.startDelay = 2.frames
- moveIn.interpolator = STATUS_BAR_X_MOVE_IN
- moveIn.addUpdateListener { animation: ValueAnimator ->
- animatedView.translationX = translationXOut * animation.animatedValue as Float
+ onTranslationXChanged(translationXOut.toFloat())
+ val moveIn = ValueAnimator.ofFloat(1f, 0f).apply {
+ duration = 23.frames
+ startDelay = 7.frames
+ interpolator = STATUS_BAR_X_MOVE_IN
+ addUpdateListener {
+ onTranslationXChanged(translationXOut * animatedValue as Float)
+ }
}
- val alphaIn = ValueAnimator.ofFloat(0f, 1f).setDuration(10.frames)
- alphaIn.startDelay = 4.frames
- alphaIn.interpolator = null
- alphaIn.addUpdateListener { animation: ValueAnimator ->
- animatedView.alpha = animation.animatedValue as Float
+ val alphaIn = ValueAnimator.ofFloat(0f, 1f).apply {
+ duration = 5.frames
+ startDelay = 11.frames
+ interpolator = null
+ addUpdateListener {
+ onAlphaChanged(animatedValue as Float)
+ }
}
val animatorSet = AnimatorSet()
animatorSet.playTogether(moveIn, alphaIn)
-
+ animatorSet.doOnEnd { isAnimationRunning = false }
+ animatorSet.doOnCancel { isAnimationRunning = false }
return animatorSet
}
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileViewLog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileViewLog.kt
new file mode 100644
index 000000000000..e594a8a5efd9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileViewLog.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.statusbar.pipeline.dagger
+
+import javax.inject.Qualifier
+
+/** Logs for changes with the new mobile views. */
+@Qualifier
+@MustBeDocumented
+@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
+annotation class MobileViewLog
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
index 44647515a6e5..adfea80715a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
@@ -148,5 +148,19 @@ abstract class StatusBarPipelineModule {
fun provideMobileInputLogBuffer(factory: LogBufferFactory): LogBuffer {
return factory.create("MobileInputLog", 100)
}
+
+ @Provides
+ @SysUISingleton
+ @MobileViewLog
+ fun provideMobileViewLogBuffer(factory: LogBufferFactory): LogBuffer {
+ return factory.create("MobileViewLog", 100)
+ }
+
+ @Provides
+ @SysUISingleton
+ @VerboseMobileViewLog
+ fun provideVerboseMobileViewLogBuffer(factory: LogBufferFactory): LogBuffer {
+ return factory.create("VerboseMobileViewLog", 100)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/VerboseMobileViewLog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/VerboseMobileViewLog.kt
new file mode 100644
index 000000000000..b98789807dd3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/VerboseMobileViewLog.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.statusbar.pipeline.dagger
+
+import javax.inject.Qualifier
+
+/** Logs for **verbose** changes with the new mobile views. */
+@Qualifier
+@MustBeDocumented
+@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
+annotation class VerboseMobileViewLog
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
index 3cbd2b76c248..4156fc152602 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.pipeline.mobile.shared
+package com.android.systemui.statusbar.pipeline.mobile.data
import android.net.Network
import android.net.NetworkCapabilities
@@ -51,8 +51,8 @@ constructor(
)
}
- fun logOnLost(network: Network) {
- LoggerHelper.logOnLost(buffer, TAG, network)
+ fun logOnLost(network: Network, isDefaultNetworkCallback: Boolean) {
+ LoggerHelper.logOnLost(buffer, TAG, network, isDefaultNetworkCallback)
}
fun logOnServiceStateChanged(serviceState: ServiceState, subId: Int) {
@@ -133,24 +133,6 @@ constructor(
)
}
- fun logUiAdapterSubIdsUpdated(subs: List<Int>) {
- buffer.log(
- TAG,
- LogLevel.INFO,
- { str1 = subs.toString() },
- { "Sub IDs in MobileUiAdapter updated internally: $str1" },
- )
- }
-
- fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) {
- buffer.log(
- TAG,
- LogLevel.INFO,
- { str1 = subs.toString() },
- { "Sub IDs in MobileUiAdapter being sent to icon controller: $str1" },
- )
- }
-
fun logCarrierConfigChanged(subId: Int) {
buffer.log(
TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
index 85729c12cd4c..19f0242040fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
@@ -24,9 +24,11 @@ import android.telephony.TelephonyManager.DATA_HANDOVER_IN_PROGRESS
import android.telephony.TelephonyManager.DATA_SUSPENDED
import android.telephony.TelephonyManager.DATA_UNKNOWN
import android.telephony.TelephonyManager.DataState
+import com.android.systemui.log.table.Diffable
+import com.android.systemui.log.table.TableRowLogger
/** Internal enum representation of the telephony data connection states */
-enum class DataConnectionState {
+enum class DataConnectionState : Diffable<DataConnectionState> {
Connected,
Connecting,
Disconnected,
@@ -34,7 +36,17 @@ enum class DataConnectionState {
Suspended,
HandoverInProgress,
Unknown,
- Invalid,
+ Invalid;
+
+ override fun logDiffs(prevVal: DataConnectionState, row: TableRowLogger) {
+ if (prevVal != this) {
+ row.logChange(COL_CONNECTION_STATE, name)
+ }
+ }
+
+ companion object {
+ private const val COL_CONNECTION_STATE = "connectionState"
+ }
}
fun @receiver:DataState Int.toDataConnectionType(): DataConnectionState =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt
deleted file mode 100644
index ed7f60b50bb9..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt
+++ /dev/null
@@ -1,176 +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.systemui.statusbar.pipeline.mobile.data.model
-
-import android.annotation.IntRange
-import android.telephony.CellSignalStrength
-import android.telephony.TelephonyCallback.CarrierNetworkListener
-import android.telephony.TelephonyCallback.DataActivityListener
-import android.telephony.TelephonyCallback.DataConnectionStateListener
-import android.telephony.TelephonyCallback.DisplayInfoListener
-import android.telephony.TelephonyCallback.ServiceStateListener
-import android.telephony.TelephonyCallback.SignalStrengthsListener
-import android.telephony.TelephonyDisplayInfo
-import android.telephony.TelephonyManager
-import androidx.annotation.VisibleForTesting
-import com.android.systemui.log.table.Diffable
-import com.android.systemui.log.table.TableRowLogger
-import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected
-import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-
-/**
- * Data class containing all of the relevant information for a particular line of service, known as
- * a Subscription in the telephony world. These models are the result of a single telephony listener
- * which has many callbacks which each modify some particular field on this object.
- *
- * The design goal here is to de-normalize fields from the system into our model fields below. So
- * any new field that needs to be tracked should be copied into this data class rather than
- * threading complex system objects through the pipeline.
- */
-data class MobileConnectionModel(
- /** Fields below are from [ServiceStateListener.onServiceStateChanged] */
- val isEmergencyOnly: Boolean = false,
- val isRoaming: Boolean = false,
- /**
- * See [android.telephony.ServiceState.getOperatorAlphaShort], this value is defined as the
- * current registered operator name in short alphanumeric format. In some cases this name might
- * be preferred over other methods of calculating the network name
- */
- val operatorAlphaShort: String? = null,
-
- /**
- * TODO (b/263167683): Clarify this field
- *
- * This check comes from [com.android.settingslib.Utils.isInService]. It is intended to be a
- * mapping from a ServiceState to a notion of connectivity. Notably, it will consider a
- * connection to be in-service if either the voice registration state is IN_SERVICE or the data
- * registration state is IN_SERVICE and NOT IWLAN.
- */
- val isInService: Boolean = false,
-
- /** Fields below from [SignalStrengthsListener.onSignalStrengthsChanged] */
- val isGsm: Boolean = false,
- @IntRange(from = 0, to = 4)
- val cdmaLevel: Int = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN,
- @IntRange(from = 0, to = 4)
- val primaryLevel: Int = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN,
-
- /** Fields below from [DataConnectionStateListener.onDataConnectionStateChanged] */
- val dataConnectionState: DataConnectionState = Disconnected,
-
- /**
- * Fields below from [DataActivityListener.onDataActivity]. See [TelephonyManager] for the
- * values
- */
- val dataActivityDirection: DataActivityModel =
- DataActivityModel(
- hasActivityIn = false,
- hasActivityOut = false,
- ),
-
- /** Fields below from [CarrierNetworkListener.onCarrierNetworkChange] */
- val carrierNetworkChangeActive: Boolean = false,
-
- /** Fields below from [DisplayInfoListener.onDisplayInfoChanged]. */
-
- /**
- * [resolvedNetworkType] is the [TelephonyDisplayInfo.getOverrideNetworkType] if it exists or
- * [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon
- */
- val resolvedNetworkType: ResolvedNetworkType = ResolvedNetworkType.UnknownNetworkType,
-) : Diffable<MobileConnectionModel> {
- override fun logDiffs(prevVal: MobileConnectionModel, row: TableRowLogger) {
- if (prevVal.dataConnectionState != dataConnectionState) {
- row.logChange(COL_CONNECTION_STATE, dataConnectionState.name)
- }
-
- if (prevVal.isEmergencyOnly != isEmergencyOnly) {
- row.logChange(COL_EMERGENCY, isEmergencyOnly)
- }
-
- if (prevVal.isRoaming != isRoaming) {
- row.logChange(COL_ROAMING, isRoaming)
- }
-
- if (prevVal.operatorAlphaShort != operatorAlphaShort) {
- row.logChange(COL_OPERATOR, operatorAlphaShort)
- }
-
- if (prevVal.isInService != isInService) {
- row.logChange(COL_IS_IN_SERVICE, isInService)
- }
-
- if (prevVal.isGsm != isGsm) {
- row.logChange(COL_IS_GSM, isGsm)
- }
-
- if (prevVal.cdmaLevel != cdmaLevel) {
- row.logChange(COL_CDMA_LEVEL, cdmaLevel)
- }
-
- if (prevVal.primaryLevel != primaryLevel) {
- row.logChange(COL_PRIMARY_LEVEL, primaryLevel)
- }
-
- if (prevVal.dataActivityDirection.hasActivityIn != dataActivityDirection.hasActivityIn) {
- row.logChange(COL_ACTIVITY_DIRECTION_IN, dataActivityDirection.hasActivityIn)
- }
-
- if (prevVal.dataActivityDirection.hasActivityOut != dataActivityDirection.hasActivityOut) {
- row.logChange(COL_ACTIVITY_DIRECTION_OUT, dataActivityDirection.hasActivityOut)
- }
-
- if (prevVal.carrierNetworkChangeActive != carrierNetworkChangeActive) {
- row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive)
- }
-
- if (prevVal.resolvedNetworkType != resolvedNetworkType) {
- row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString())
- }
- }
-
- override fun logFull(row: TableRowLogger) {
- row.logChange(COL_CONNECTION_STATE, dataConnectionState.name)
- row.logChange(COL_EMERGENCY, isEmergencyOnly)
- row.logChange(COL_ROAMING, isRoaming)
- row.logChange(COL_OPERATOR, operatorAlphaShort)
- row.logChange(COL_IS_IN_SERVICE, isInService)
- row.logChange(COL_IS_GSM, isGsm)
- row.logChange(COL_CDMA_LEVEL, cdmaLevel)
- row.logChange(COL_PRIMARY_LEVEL, primaryLevel)
- row.logChange(COL_ACTIVITY_DIRECTION_IN, dataActivityDirection.hasActivityIn)
- row.logChange(COL_ACTIVITY_DIRECTION_OUT, dataActivityDirection.hasActivityOut)
- row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive)
- row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString())
- }
-
- @VisibleForTesting
- companion object {
- const val COL_EMERGENCY = "EmergencyOnly"
- const val COL_ROAMING = "Roaming"
- const val COL_OPERATOR = "OperatorName"
- const val COL_IS_IN_SERVICE = "IsInService"
- const val COL_IS_GSM = "IsGsm"
- const val COL_CDMA_LEVEL = "CdmaLevel"
- const val COL_PRIMARY_LEVEL = "PrimaryLevel"
- const val COL_CONNECTION_STATE = "ConnectionState"
- const val COL_ACTIVITY_DIRECTION_IN = "DataActivity.In"
- const val COL_ACTIVITY_DIRECTION_OUT = "DataActivity.Out"
- const val COL_CARRIER_NETWORK_CHANGE = "CarrierNetworkChangeActive"
- const val COL_RESOLVED_NETWORK_TYPE = "NetworkType"
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
index 5562e73f0478..cf7a313a4cb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
@@ -17,8 +17,12 @@
package com.android.systemui.statusbar.pipeline.mobile.data.model
import android.telephony.Annotation.NetworkType
+import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
import com.android.settingslib.SignalIcon
+import com.android.settingslib.mobile.MobileMappings
import com.android.settingslib.mobile.TelephonyIcons
+import com.android.systemui.log.table.Diffable
+import com.android.systemui.log.table.TableRowLogger
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
/**
@@ -26,11 +30,19 @@ import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
* on whether or not the display info contains an override type, we may have to call different
* methods on [MobileMappingsProxy] to generate an icon lookup key.
*/
-sealed interface ResolvedNetworkType {
+sealed interface ResolvedNetworkType : Diffable<ResolvedNetworkType> {
val lookupKey: String
+ override fun logDiffs(prevVal: ResolvedNetworkType, row: TableRowLogger) {
+ if (prevVal != this) {
+ row.logChange(COL_NETWORK_TYPE, this.toString())
+ }
+ }
+
object UnknownNetworkType : ResolvedNetworkType {
- override val lookupKey: String = "unknown"
+ override val lookupKey: String = MobileMappings.toIconKey(NETWORK_TYPE_UNKNOWN)
+
+ override fun toString(): String = "Unknown"
}
data class DefaultNetworkType(
@@ -47,5 +59,11 @@ sealed interface ResolvedNetworkType {
override val lookupKey: String = "cwf"
val iconGroupOverride: SignalIcon.MobileIconGroup = TelephonyIcons.CARRIER_MERGED_WIFI
+
+ override fun toString(): String = "CarrierMerged"
+ }
+
+ companion object {
+ private const val COL_NETWORK_TYPE = "networkType"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
index 8c82fbac90b8..f4e3eab8593d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
@@ -45,7 +45,7 @@ import kotlinx.coroutines.flow.asStateFlow
* 1. Define a new `private val` wrapping the key using [BooleanCarrierConfig]
* 2. Define a public `val` exposing the wrapped flow using [BooleanCarrierConfig.config]
* 3. Add the new [BooleanCarrierConfig] to the list of tracked configs, so they are properly
- * updated when a new carrier config comes down
+ * updated when a new carrier config comes down
*/
class SystemUiCarrierConfig
internal constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
index bb3b9b2166c3..efdce062bb37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
@@ -30,8 +30,8 @@ import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
index 6187f64e011d..90c32dc08045 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
@@ -17,11 +17,12 @@
package com.android.systemui.statusbar.pipeline.mobile.data.repository
import android.telephony.SubscriptionInfo
-import android.telephony.TelephonyCallback
import android.telephony.TelephonyManager
import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import kotlinx.coroutines.flow.StateFlow
/**
@@ -45,11 +46,57 @@ interface MobileConnectionRepository {
*/
val tableLogBuffer: TableLogBuffer
+ /** True if the [android.telephony.ServiceState] says this connection is emergency calls only */
+ val isEmergencyOnly: StateFlow<Boolean>
+
+ /** True if [android.telephony.ServiceState] says we are roaming */
+ val isRoaming: StateFlow<Boolean>
+
+ /**
+ * See [android.telephony.ServiceState.getOperatorAlphaShort], this value is defined as the
+ * current registered operator name in short alphanumeric format. In some cases this name might
+ * be preferred over other methods of calculating the network name
+ */
+ val operatorAlphaShort: StateFlow<String?>
+
+ /**
+ * TODO (b/263167683): Clarify this field
+ *
+ * This check comes from [com.android.settingslib.Utils.isInService]. It is intended to be a
+ * mapping from a ServiceState to a notion of connectivity. Notably, it will consider a
+ * connection to be in-service if either the voice registration state is IN_SERVICE or the data
+ * registration state is IN_SERVICE and NOT IWLAN.
+ */
+ val isInService: StateFlow<Boolean>
+
+ /** True if [android.telephony.SignalStrength] told us that this connection is using GSM */
+ val isGsm: StateFlow<Boolean>
+
+ /**
+ * There is still specific logic in the pipeline that calls out CDMA level explicitly. This
+ * field is not completely orthogonal to [primaryLevel], because CDMA could be primary.
+ */
+ // @IntRange(from = 0, to = 4)
+ val cdmaLevel: StateFlow<Int>
+
+ /** [android.telephony.SignalStrength]'s concept of the overall signal level */
+ // @IntRange(from = 0, to = 4)
+ val primaryLevel: StateFlow<Int>
+
+ /** The current data connection state. See [DataConnectionState] */
+ val dataConnectionState: StateFlow<DataConnectionState>
+
+ /** The current data activity direction. See [DataActivityModel] */
+ val dataActivityDirection: StateFlow<DataActivityModel>
+
+ /** True if there is currently a carrier network change in process */
+ val carrierNetworkChangeActive: StateFlow<Boolean>
+
/**
- * A flow that aggregates all necessary callbacks from [TelephonyCallback] into a single
- * listener + model.
+ * [resolvedNetworkType] is the [TelephonyDisplayInfo.getOverrideNetworkType] if it exists or
+ * [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon
*/
- val connectionInfo: StateFlow<MobileConnectionModel>
+ val resolvedNetworkType: StateFlow<ResolvedNetworkType>
/** The total number of levels. Used with [SignalDrawable]. */
val numberOfLevels: StateFlow<Int>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt
new file mode 100644
index 000000000000..809772eec2f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt
@@ -0,0 +1,231 @@
+/*
+ * 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.statusbar.pipeline.mobile.data.repository.demo
+
+import android.telephony.CellSignalStrength
+import android.telephony.TelephonyManager
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logDiffsForTable
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
+import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CARRIER_NETWORK_CHANGE
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CDMA_LEVEL
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_EMERGENCY
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_GSM
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_IN_SERVICE
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_OPERATOR
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_PRIMARY_LEVEL
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_ROAMING
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
+import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * Demo version of [MobileConnectionRepository]. Note that this class shares all of its flows using
+ * [SharingStarted.WhileSubscribed()] to give the same semantics as using a regular
+ * [MutableStateFlow] while still logging all of the inputs in the same manor as the production
+ * repos.
+ */
+class DemoMobileConnectionRepository(
+ override val subId: Int,
+ override val tableLogBuffer: TableLogBuffer,
+ val scope: CoroutineScope,
+) : MobileConnectionRepository {
+ private val _isEmergencyOnly = MutableStateFlow(false)
+ override val isEmergencyOnly =
+ _isEmergencyOnly
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_EMERGENCY,
+ _isEmergencyOnly.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), _isEmergencyOnly.value)
+
+ private val _isRoaming = MutableStateFlow(false)
+ override val isRoaming =
+ _isRoaming
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_ROAMING,
+ _isRoaming.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), _isRoaming.value)
+
+ private val _operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null)
+ override val operatorAlphaShort =
+ _operatorAlphaShort
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_OPERATOR,
+ _operatorAlphaShort.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), _operatorAlphaShort.value)
+
+ private val _isInService = MutableStateFlow(false)
+ override val isInService =
+ _isInService
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_IS_IN_SERVICE,
+ _isInService.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), _isInService.value)
+
+ private val _isGsm = MutableStateFlow(false)
+ override val isGsm =
+ _isGsm
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_IS_GSM,
+ _isGsm.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), _isGsm.value)
+
+ private val _cdmaLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+ override val cdmaLevel =
+ _cdmaLevel
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_CDMA_LEVEL,
+ _cdmaLevel.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), _cdmaLevel.value)
+
+ private val _primaryLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+ override val primaryLevel =
+ _primaryLevel
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_PRIMARY_LEVEL,
+ _primaryLevel.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), _primaryLevel.value)
+
+ private val _dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected)
+ override val dataConnectionState =
+ _dataConnectionState
+ .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataConnectionState.value)
+ .stateIn(scope, SharingStarted.WhileSubscribed(), _dataConnectionState.value)
+
+ private val _dataActivityDirection =
+ MutableStateFlow(
+ DataActivityModel(
+ hasActivityIn = false,
+ hasActivityOut = false,
+ )
+ )
+ override val dataActivityDirection =
+ _dataActivityDirection
+ .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataActivityDirection.value)
+ .stateIn(scope, SharingStarted.WhileSubscribed(), _dataActivityDirection.value)
+
+ private val _carrierNetworkChangeActive = MutableStateFlow(false)
+ override val carrierNetworkChangeActive =
+ _carrierNetworkChangeActive
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_CARRIER_NETWORK_CHANGE,
+ _carrierNetworkChangeActive.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), _carrierNetworkChangeActive.value)
+
+ private val _resolvedNetworkType: MutableStateFlow<ResolvedNetworkType> =
+ MutableStateFlow(ResolvedNetworkType.UnknownNetworkType)
+ override val resolvedNetworkType =
+ _resolvedNetworkType
+ .logDiffsForTable(tableLogBuffer, columnPrefix = "", _resolvedNetworkType.value)
+ .stateIn(scope, SharingStarted.WhileSubscribed(), _resolvedNetworkType.value)
+
+ override val numberOfLevels = MutableStateFlow(MobileConnectionRepository.DEFAULT_NUM_LEVELS)
+
+ override val dataEnabled = MutableStateFlow(true)
+
+ override val cdmaRoaming = MutableStateFlow(false)
+
+ override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network"))
+
+ /**
+ * Process a new demo mobile event. Note that [resolvedNetworkType] must be passed in separately
+ * from the event, due to the requirement to reverse the mobile mappings lookup in the top-level
+ * repository.
+ */
+ fun processDemoMobileEvent(
+ event: FakeNetworkEventModel.Mobile,
+ resolvedNetworkType: ResolvedNetworkType,
+ ) {
+ // This is always true here, because we split out disabled states at the data-source level
+ dataEnabled.value = true
+ networkName.value = NetworkNameModel.IntentDerived(event.name)
+
+ cdmaRoaming.value = event.roaming
+ _isRoaming.value = event.roaming
+ // TODO(b/261029387): not yet supported
+ _isEmergencyOnly.value = false
+ _operatorAlphaShort.value = event.name
+ _isInService.value = (event.level ?: 0) > 0
+ // TODO(b/261029387): not yet supported
+ _isGsm.value = false
+ _cdmaLevel.value = event.level ?: 0
+ _primaryLevel.value = event.level ?: 0
+ // TODO(b/261029387): not yet supported
+ _dataConnectionState.value = DataConnectionState.Connected
+ _dataActivityDirection.value =
+ (event.activity ?: TelephonyManager.DATA_ACTIVITY_NONE).toMobileDataActivityModel()
+ _carrierNetworkChangeActive.value = event.carrierNetworkChange
+ _resolvedNetworkType.value = resolvedNetworkType
+ }
+
+ fun processCarrierMergedEvent(event: FakeWifiEventModel.CarrierMerged) {
+ // This is always true here, because we split out disabled states at the data-source level
+ dataEnabled.value = true
+ networkName.value = NetworkNameModel.IntentDerived(CARRIER_MERGED_NAME)
+ numberOfLevels.value = event.numberOfLevels
+ cdmaRoaming.value = false
+ _primaryLevel.value = event.level
+ _cdmaLevel.value = event.level
+ _dataActivityDirection.value = event.activity.toMobileDataActivityModel()
+
+ // These fields are always the same for carrier-merged networks
+ _resolvedNetworkType.value = ResolvedNetworkType.CarrierMergedNetworkType
+ _dataConnectionState.value = DataConnectionState.Connected
+ _isRoaming.value = false
+ _isEmergencyOnly.value = false
+ _operatorAlphaShort.value = null
+ _isInService.value = true
+ _isGsm.value = false
+ _carrierNetworkChangeActive.value = false
+ }
+
+ companion object {
+ private const val CARRIER_MERGED_NAME = "Carrier Merged Network"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
index e92483232186..3cafb7377260 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
@@ -18,30 +18,22 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo
import android.content.Context
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
-import android.telephony.TelephonyManager.DATA_ACTIVITY_NONE
import android.util.Log
import com.android.settingslib.SignalIcon
import com.android.settingslib.mobile.MobileMappings
import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
-import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
-import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.Mobile
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.CarrierMergedConnectionRepository.Companion.createCarrierMergedConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.MOBILE_CONNECTION_BUFFER_SIZE
-import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
import javax.inject.Inject
@@ -183,7 +175,7 @@ constructor(
private fun createDemoMobileConnectionRepo(subId: Int): CacheContainer {
val tableLogBuffer =
logFactory.getOrCreate(
- "DemoMobileConnectionLog [$subId]",
+ "DemoMobileConnectionLog[$subId]",
MOBILE_CONNECTION_BUFFER_SIZE,
)
@@ -191,6 +183,7 @@ constructor(
DemoMobileConnectionRepository(
subId,
tableLogBuffer,
+ scope,
)
return CacheContainer(repo, lastMobileState = null)
}
@@ -237,23 +230,18 @@ constructor(
}
}
- private fun processEnabledMobileState(state: Mobile) {
+ private fun processEnabledMobileState(event: Mobile) {
// get or create the connection repo, and set its values
- val subId = state.subId ?: DEFAULT_SUB_ID
+ val subId = event.subId ?: DEFAULT_SUB_ID
maybeCreateSubscription(subId)
val connection = getRepoForSubId(subId)
- connectionRepoCache[subId]?.lastMobileState = state
+ connectionRepoCache[subId]?.lastMobileState = event
// TODO(b/261029387): until we have a command, use the most recent subId
defaultDataSubId.value = subId
- // This is always true here, because we split out disabled states at the data-source level
- connection.dataEnabled.value = true
- connection.networkName.value = NetworkNameModel.IntentDerived(state.name)
-
- connection.cdmaRoaming.value = state.roaming
- connection.connectionInfo.value = state.toMobileConnectionModel()
+ connection.processDemoMobileEvent(event, event.dataType.toResolvedNetworkType())
}
private fun processCarrierMergedWifiState(event: FakeWifiEventModel.CarrierMerged) {
@@ -272,13 +260,7 @@ constructor(
defaultDataSubId.value = subId
val connection = getRepoForSubId(subId)
- // This is always true here, because we split out disabled states at the data-source level
- connection.dataEnabled.value = true
- connection.networkName.value = NetworkNameModel.IntentDerived(CARRIER_MERGED_NAME)
- connection.numberOfLevels.value = event.numberOfLevels
- connection.cdmaRoaming.value = false
- connection.connectionInfo.value = event.toMobileConnectionModel()
- Log.e("CCS", "output connection info = ${connection.connectionInfo.value}")
+ connection.processCarrierMergedEvent(event)
}
private fun maybeRemoveSubscription(subId: Int?) {
@@ -332,29 +314,6 @@ constructor(
private fun subIdsString(): String =
_subscriptions.value.joinToString(",") { it.subscriptionId.toString() }
- private fun Mobile.toMobileConnectionModel(): MobileConnectionModel {
- return MobileConnectionModel(
- isEmergencyOnly = false, // TODO(b/261029387): not yet supported
- isRoaming = roaming,
- isInService = (level ?: 0) > 0,
- isGsm = false, // TODO(b/261029387): not yet supported
- cdmaLevel = level ?: 0,
- primaryLevel = level ?: 0,
- dataConnectionState =
- DataConnectionState.Connected, // TODO(b/261029387): not yet supported
- dataActivityDirection = (activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel(),
- carrierNetworkChangeActive = carrierNetworkChange,
- resolvedNetworkType = dataType.toResolvedNetworkType()
- )
- }
-
- private fun FakeWifiEventModel.CarrierMerged.toMobileConnectionModel(): MobileConnectionModel {
- return createCarrierMergedConnectionModel(
- this.level,
- activity.toMobileDataActivityModel(),
- )
- }
-
private fun SignalIcon.MobileIconGroup?.toResolvedNetworkType(): ResolvedNetworkType {
val key = mobileMappingsReverseLookup.value[this] ?: "dis"
return DefaultNetworkType(key)
@@ -364,8 +323,6 @@ constructor(
private const val TAG = "DemoMobileConnectionsRepo"
private const val DEFAULT_SUB_ID = 1
-
- private const val CARRIER_MERGED_NAME = "Carrier Merged Network"
}
}
@@ -374,18 +331,3 @@ class CacheContainer(
/** The last received [Mobile] event. Used when switching from carrier merged back to mobile. */
var lastMobileState: Mobile?,
)
-
-class DemoMobileConnectionRepository(
- override val subId: Int,
- override val tableLogBuffer: TableLogBuffer,
-) : MobileConnectionRepository {
- override val connectionInfo = MutableStateFlow(MobileConnectionModel())
-
- override val numberOfLevels = MutableStateFlow(DEFAULT_NUM_LEVELS)
-
- override val dataEnabled = MutableStateFlow(true)
-
- override val cdmaRoaming = MutableStateFlow(false)
-
- override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network"))
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
index 8f6a87b089f2..94d6d0b1db44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
@@ -16,18 +16,17 @@
package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
+import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
import android.telephony.TelephonyManager
import android.util.Log
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
-import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import javax.inject.Inject
@@ -94,16 +93,6 @@ class CarrierMergedConnectionRepository(
}
}
- override val connectionInfo: StateFlow<MobileConnectionModel> =
- combine(network, wifiRepository.wifiActivity) { network, activity ->
- if (network == null) {
- MobileConnectionModel()
- } else {
- createCarrierMergedConnectionModel(network.level, activity)
- }
- }
- .stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectionModel())
-
override val cdmaRoaming: StateFlow<Boolean> = MutableStateFlow(ROAMING).asStateFlow()
override val networkName: StateFlow<NetworkNameModel> =
@@ -129,34 +118,54 @@ class CarrierMergedConnectionRepository(
}
.stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS)
- override val dataEnabled: StateFlow<Boolean> = wifiRepository.isWifiEnabled
+ override val primaryLevel =
+ network
+ .map { it?.level ?: SIGNAL_STRENGTH_NONE_OR_UNKNOWN }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
- companion object {
- /**
- * Creates an instance of [MobileConnectionModel] that represents a carrier merged network
- * with the given [level] and [activity].
- */
- fun createCarrierMergedConnectionModel(
- level: Int,
- activity: DataActivityModel,
- ): MobileConnectionModel {
- return MobileConnectionModel(
- primaryLevel = level,
- cdmaLevel = level,
- dataActivityDirection = activity,
- // Here and below: These values are always the same for every carrier-merged
- // connection.
- resolvedNetworkType = ResolvedNetworkType.CarrierMergedNetworkType,
- dataConnectionState = DataConnectionState.Connected,
- isRoaming = ROAMING,
- isEmergencyOnly = false,
- operatorAlphaShort = null,
- isInService = true,
- isGsm = false,
- carrierNetworkChangeActive = false,
+ override val cdmaLevel =
+ network
+ .map { it?.level ?: SIGNAL_STRENGTH_NONE_OR_UNKNOWN }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+
+ override val dataActivityDirection = wifiRepository.wifiActivity
+
+ override val resolvedNetworkType =
+ network
+ .map {
+ if (it != null) {
+ ResolvedNetworkType.CarrierMergedNetworkType
+ } else {
+ ResolvedNetworkType.UnknownNetworkType
+ }
+ }
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ ResolvedNetworkType.UnknownNetworkType
)
- }
+ override val dataConnectionState =
+ network
+ .map {
+ if (it != null) {
+ DataConnectionState.Connected
+ } else {
+ DataConnectionState.Disconnected
+ }
+ }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), DataConnectionState.Disconnected)
+
+ override val isRoaming = MutableStateFlow(false).asStateFlow()
+ override val isEmergencyOnly = MutableStateFlow(false).asStateFlow()
+ override val operatorAlphaShort = MutableStateFlow(null).asStateFlow()
+ override val isInService = MutableStateFlow(true).asStateFlow()
+ override val isGsm = MutableStateFlow(false).asStateFlow()
+ override val carrierNetworkChangeActive = MutableStateFlow(false).asStateFlow()
+
+ override val dataEnabled: StateFlow<Boolean> = wifiRepository.isWifiEnabled
+
+ companion object {
// Carrier merged is never roaming
private const val ROAMING = false
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
index a39ea0abce5a..b3737ecd1e0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
@@ -114,15 +114,147 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.cdmaRoaming }
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.cdmaRoaming.value)
- override val connectionInfo =
+ override val isEmergencyOnly =
activeRepo
- .flatMapLatest { it.connectionInfo }
+ .flatMapLatest { it.isEmergencyOnly }
.logDiffsForTable(
tableLogBuffer,
columnPrefix = "",
- initialValue = activeRepo.value.connectionInfo.value,
+ columnName = COL_EMERGENCY,
+ activeRepo.value.isEmergencyOnly.value
+ )
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ activeRepo.value.isEmergencyOnly.value
+ )
+
+ override val isRoaming =
+ activeRepo
+ .flatMapLatest { it.isRoaming }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_ROAMING,
+ activeRepo.value.isRoaming.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isRoaming.value)
+
+ override val operatorAlphaShort =
+ activeRepo
+ .flatMapLatest { it.operatorAlphaShort }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_OPERATOR,
+ activeRepo.value.operatorAlphaShort.value
+ )
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ activeRepo.value.operatorAlphaShort.value
+ )
+
+ override val isInService =
+ activeRepo
+ .flatMapLatest { it.isInService }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_IS_IN_SERVICE,
+ activeRepo.value.isInService.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isInService.value)
+
+ override val isGsm =
+ activeRepo
+ .flatMapLatest { it.isGsm }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_IS_GSM,
+ activeRepo.value.isGsm.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isGsm.value)
+
+ override val cdmaLevel =
+ activeRepo
+ .flatMapLatest { it.cdmaLevel }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_CDMA_LEVEL,
+ activeRepo.value.cdmaLevel.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.cdmaLevel.value)
+
+ override val primaryLevel =
+ activeRepo
+ .flatMapLatest { it.primaryLevel }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_PRIMARY_LEVEL,
+ activeRepo.value.primaryLevel.value
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.primaryLevel.value)
+
+ override val dataConnectionState =
+ activeRepo
+ .flatMapLatest { it.dataConnectionState }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ activeRepo.value.dataConnectionState.value
+ )
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ activeRepo.value.dataConnectionState.value
+ )
+
+ override val dataActivityDirection =
+ activeRepo
+ .flatMapLatest { it.dataActivityDirection }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ activeRepo.value.dataActivityDirection.value
+ )
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ activeRepo.value.dataActivityDirection.value
+ )
+
+ override val carrierNetworkChangeActive =
+ activeRepo
+ .flatMapLatest { it.carrierNetworkChangeActive }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = COL_CARRIER_NETWORK_CHANGE,
+ activeRepo.value.carrierNetworkChangeActive.value
+ )
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ activeRepo.value.carrierNetworkChangeActive.value
+ )
+
+ override val resolvedNetworkType =
+ activeRepo
+ .flatMapLatest { it.resolvedNetworkType }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ activeRepo.value.resolvedNetworkType.value
+ )
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ activeRepo.value.resolvedNetworkType.value
)
- .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.connectionInfo.value)
override val dataEnabled =
activeRepo
@@ -187,4 +319,15 @@ class FullMobileConnectionRepository(
fun tableBufferLogName(subId: Int): String = "MobileConnectionLog[$subId]"
}
}
+
+ companion object {
+ const val COL_EMERGENCY = "emergencyOnly"
+ const val COL_ROAMING = "roaming"
+ const val COL_OPERATOR = "operatorName"
+ const val COL_IS_IN_SERVICE = "isInService"
+ const val COL_IS_GSM = "isGsm"
+ const val COL_CDMA_LEVEL = "cdmaLevel"
+ const val COL_PRIMARY_LEVEL = "primaryLevel"
+ const val COL_CARRIER_NETWORK_CHANGE = "carrierNetworkChangeActive"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
index 96b96f14d6aa..f866d65e2d2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
@@ -18,7 +18,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
import android.content.Context
import android.content.IntentFilter
-import android.telephony.CellSignalStrength
+import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
import android.telephony.CellSignalStrengthCdma
import android.telephony.ServiceState
import android.telephony.SignalStrength
@@ -27,16 +27,17 @@ import android.telephony.TelephonyCallback
import android.telephony.TelephonyDisplayInfo
import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
import android.telephony.TelephonyManager
-import android.telephony.TelephonyManager.ERI_OFF
+import android.telephony.TelephonyManager.ERI_FLASH
+import android.telephony.TelephonyManager.ERI_ON
import android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
import com.android.settingslib.Utils
import com.android.systemui.broadcast.BroadcastDispatcher
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
@@ -47,8 +48,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameMo
import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -57,16 +58,14 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.scan
-import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
/**
@@ -98,8 +97,6 @@ class MobileConnectionRepositoryImpl(
}
}
- private val telephonyCallbackEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
-
/**
* This flow defines the single shared connection to system_server via TelephonyCallback. Any
* new callback should be added to this listener and funneled through callbackEvents via a data
@@ -107,9 +104,15 @@ class MobileConnectionRepositoryImpl(
*
* The reason we need to do this is because TelephonyManager limits the number of registered
* listeners per-process, so we don't want to create a new listener for every callback.
+ *
+ * A note on the design for back pressure here: We use the [coalesce] operator here to change
+ * the backpressure strategy to store exactly the last callback event of _each type_ here, as
+ * opposed to the default strategy which is to drop the oldest event (regardless of type). This
+ * means that we should never miss any single event as long as the flow has been started.
*/
- private val callbackEvents: SharedFlow<CallbackEvent> =
- conflatedCallbackFlow {
+ private val callbackEvents: StateFlow<TelephonyCallbackState> = run {
+ val initial = TelephonyCallbackState()
+ callbackFlow {
val callback =
object :
TelephonyCallback(),
@@ -163,85 +166,102 @@ class MobileConnectionRepositoryImpl(
telephonyManager.registerTelephonyCallback(bgDispatcher.asExecutor(), callback)
awaitClose { telephonyManager.unregisterTelephonyCallback(callback) }
}
- .shareIn(scope, SharingStarted.WhileSubscribed())
+ .scan(initial = initial) { state, event -> state.applyEvent(event) }
+ .stateIn(scope = scope, started = SharingStarted.WhileSubscribed(), initial)
+ }
- private fun updateConnectionState(
- prevState: MobileConnectionModel,
- callbackEvent: CallbackEvent,
- ): MobileConnectionModel =
- when (callbackEvent) {
- is CallbackEvent.OnServiceStateChanged -> {
- val serviceState = callbackEvent.serviceState
- prevState.copy(
- isEmergencyOnly = serviceState.isEmergencyOnly,
- isRoaming = serviceState.roaming,
- operatorAlphaShort = serviceState.operatorAlphaShort,
- isInService = Utils.isInService(serviceState),
- )
- }
- is CallbackEvent.OnSignalStrengthChanged -> {
- val signalStrength = callbackEvent.signalStrength
- val cdmaLevel =
- signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java).let {
- strengths ->
- if (!strengths.isEmpty()) {
- strengths[0].level
- } else {
- CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
- }
- }
+ override val isEmergencyOnly =
+ callbackEvents
+ .mapNotNull { it.onServiceStateChanged }
+ .map { it.serviceState.isEmergencyOnly }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), false)
- val primaryLevel = signalStrength.level
+ override val isRoaming =
+ callbackEvents
+ .mapNotNull { it.onServiceStateChanged }
+ .map { it.serviceState.roaming }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), false)
- prevState.copy(
- cdmaLevel = cdmaLevel,
- primaryLevel = primaryLevel,
- isGsm = signalStrength.isGsm,
- )
- }
- is CallbackEvent.OnDataConnectionStateChanged -> {
- prevState.copy(dataConnectionState = callbackEvent.dataState.toDataConnectionType())
- }
- is CallbackEvent.OnDataActivity -> {
- prevState.copy(
- dataActivityDirection = callbackEvent.direction.toMobileDataActivityModel()
- )
- }
- is CallbackEvent.OnCarrierNetworkChange -> {
- prevState.copy(carrierNetworkChangeActive = callbackEvent.active)
- }
- is CallbackEvent.OnDisplayInfoChanged -> {
- val telephonyDisplayInfo = callbackEvent.telephonyDisplayInfo
- val networkType =
- if (telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) {
- UnknownNetworkType
- } else if (
- telephonyDisplayInfo.overrideNetworkType == OVERRIDE_NETWORK_TYPE_NONE
- ) {
- DefaultNetworkType(
- mobileMappingsProxy.toIconKey(telephonyDisplayInfo.networkType)
- )
+ override val operatorAlphaShort =
+ callbackEvents
+ .mapNotNull { it.onServiceStateChanged }
+ .map { it.serviceState.operatorAlphaShort }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), null)
+
+ override val isInService =
+ callbackEvents
+ .mapNotNull { it.onServiceStateChanged }
+ .map { Utils.isInService(it.serviceState) }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+ override val isGsm =
+ callbackEvents
+ .mapNotNull { it.onSignalStrengthChanged }
+ .map { it.signalStrength.isGsm }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+ override val cdmaLevel =
+ callbackEvents
+ .mapNotNull { it.onSignalStrengthChanged }
+ .map {
+ it.signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java).let {
+ strengths ->
+ if (strengths.isNotEmpty()) {
+ strengths[0].level
} else {
- OverrideNetworkType(
- mobileMappingsProxy.toIconKeyOverride(
- telephonyDisplayInfo.overrideNetworkType
- )
- )
+ SIGNAL_STRENGTH_NONE_OR_UNKNOWN
}
- prevState.copy(resolvedNetworkType = networkType)
- }
- is CallbackEvent.OnDataEnabledChanged -> {
- // Not part of this object, handled in a separate flow
- prevState
+ }
}
- }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
- override val connectionInfo = run {
- val initial = MobileConnectionModel()
+ override val primaryLevel =
callbackEvents
- .scan(initial, ::updateConnectionState)
- .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
- }
+ .mapNotNull { it.onSignalStrengthChanged }
+ .map { it.signalStrength.level }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+
+ override val dataConnectionState =
+ callbackEvents
+ .mapNotNull { it.onDataConnectionStateChanged }
+ .map { it.dataState.toDataConnectionType() }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), Disconnected)
+
+ override val dataActivityDirection =
+ callbackEvents
+ .mapNotNull { it.onDataActivity }
+ .map { it.direction.toMobileDataActivityModel() }
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ DataActivityModel(hasActivityIn = false, hasActivityOut = false)
+ )
+
+ override val carrierNetworkChangeActive =
+ callbackEvents
+ .mapNotNull { it.onCarrierNetworkChange }
+ .map { it.active }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+ override val resolvedNetworkType =
+ callbackEvents
+ .mapNotNull { it.onDisplayInfoChanged }
+ .map {
+ if (it.telephonyDisplayInfo.overrideNetworkType != OVERRIDE_NETWORK_TYPE_NONE) {
+ OverrideNetworkType(
+ mobileMappingsProxy.toIconKeyOverride(
+ it.telephonyDisplayInfo.overrideNetworkType
+ )
+ )
+ } else if (it.telephonyDisplayInfo.networkType != NETWORK_TYPE_UNKNOWN) {
+ DefaultNetworkType(
+ mobileMappingsProxy.toIconKey(it.telephonyDisplayInfo.networkType)
+ )
+ } else {
+ UnknownNetworkType
+ }
+ }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), UnknownNetworkType)
override val numberOfLevels =
systemUiCarrierConfig.shouldInflateSignalStrength
@@ -263,7 +283,10 @@ class MobileConnectionRepositoryImpl(
override val cdmaRoaming: StateFlow<Boolean> =
telephonyPollingEvent
- .mapLatest { telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber != ERI_OFF }
+ .mapLatest {
+ val cdmaEri = telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber
+ cdmaEri == ERI_ON || cdmaEri == ERI_FLASH
+ }
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val networkName: StateFlow<NetworkNameModel> =
@@ -281,7 +304,8 @@ class MobileConnectionRepositoryImpl(
override val dataEnabled = run {
val initial = telephonyManager.isDataConnectionAllowed
callbackEvents
- .mapNotNull { (it as? CallbackEvent.OnDataEnabledChanged)?.enabled }
+ .mapNotNull { it.onDataEnabledChanged }
+ .map { it.enabled }
.stateIn(scope, SharingStarted.WhileSubscribed(), initial)
}
@@ -325,12 +349,41 @@ class MobileConnectionRepositoryImpl(
* Wrap every [TelephonyCallback] we care about in a data class so we can accept them in a single
* shared flow and then split them back out into other flows.
*/
-private sealed interface CallbackEvent {
- data class OnServiceStateChanged(val serviceState: ServiceState) : CallbackEvent
- data class OnSignalStrengthChanged(val signalStrength: SignalStrength) : CallbackEvent
- data class OnDataConnectionStateChanged(val dataState: Int) : CallbackEvent
- data class OnDataActivity(val direction: Int) : CallbackEvent
+sealed interface CallbackEvent {
data class OnCarrierNetworkChange(val active: Boolean) : CallbackEvent
- data class OnDisplayInfoChanged(val telephonyDisplayInfo: TelephonyDisplayInfo) : CallbackEvent
+ data class OnDataActivity(val direction: Int) : CallbackEvent
+ data class OnDataConnectionStateChanged(val dataState: Int) : CallbackEvent
data class OnDataEnabledChanged(val enabled: Boolean) : CallbackEvent
+ data class OnDisplayInfoChanged(val telephonyDisplayInfo: TelephonyDisplayInfo) : CallbackEvent
+ data class OnServiceStateChanged(val serviceState: ServiceState) : CallbackEvent
+ data class OnSignalStrengthChanged(val signalStrength: SignalStrength) : CallbackEvent
+}
+
+/**
+ * A simple box type for 1-to-1 mapping of [CallbackEvent] to the batched event. Used in conjunction
+ * with [scan] to make sure we don't drop important callbacks due to late subscribers
+ */
+data class TelephonyCallbackState(
+ val onDataActivity: CallbackEvent.OnDataActivity? = null,
+ val onCarrierNetworkChange: CallbackEvent.OnCarrierNetworkChange? = null,
+ val onDataConnectionStateChanged: CallbackEvent.OnDataConnectionStateChanged? = null,
+ val onDataEnabledChanged: CallbackEvent.OnDataEnabledChanged? = null,
+ val onDisplayInfoChanged: CallbackEvent.OnDisplayInfoChanged? = null,
+ val onServiceStateChanged: CallbackEvent.OnServiceStateChanged? = null,
+ val onSignalStrengthChanged: CallbackEvent.OnSignalStrengthChanged? = null,
+) {
+ fun applyEvent(event: CallbackEvent): TelephonyCallbackState {
+ return when (event) {
+ is CallbackEvent.OnCarrierNetworkChange -> copy(onCarrierNetworkChange = event)
+ is CallbackEvent.OnDataActivity -> copy(onDataActivity = event)
+ is CallbackEvent.OnDataConnectionStateChanged ->
+ copy(onDataConnectionStateChanged = event)
+ is CallbackEvent.OnDataEnabledChanged -> copy(onDataEnabledChanged = event)
+ is CallbackEvent.OnDisplayInfoChanged -> copy(onDisplayInfoChanged = event)
+ is CallbackEvent.OnServiceStateChanged -> {
+ copy(onServiceStateChanged = event)
+ }
+ is CallbackEvent.OnSignalStrengthChanged -> copy(onSignalStrengthChanged = event)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index b3d5b1e7e450..b7da3f27c70a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -45,11 +45,11 @@ import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.pipeline.dagger.MobileSummaryLog
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
@@ -266,6 +266,7 @@ constructor(
val callback =
object : NetworkCallback(FLAG_INCLUDE_LOCATION_INFO) {
override fun onLost(network: Network) {
+ logger.logOnLost(network, isDefaultNetworkCallback = true)
// Send a disconnected model when lost. Maybe should create a sealed
// type or null here?
trySend(MobileConnectivityModel())
@@ -275,6 +276,11 @@ constructor(
network: Network,
caps: NetworkCapabilities
) {
+ logger.logOnCapabilitiesChanged(
+ network,
+ caps,
+ isDefaultNetworkCallback = true,
+ )
trySend(
MobileConnectivityModel(
isConnected = caps.hasTransport(TRANSPORT_CELLULAR),
@@ -353,8 +359,8 @@ constructor(
* True if the checked subId is in the list of current subs or the active mobile data subId
*
* @param checkedSubs the list to validate [subId] against. To invalidate the cache, pass in the
- * new subscription list. Otherwise use [subscriptions.value] to validate a subId against the
- * current known subscriptions
+ * new subscription list. Otherwise use [subscriptions.value] to validate a subId against the
+ * current known subscriptions
*/
private fun checkSub(subId: Int, checkedSubs: List<SubscriptionModel>): Boolean {
if (activeMobileDataSubscriptionId.value == subId) return true
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
index 7b0f95271d63..7df6764fda1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
@@ -34,6 +34,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
@@ -92,7 +93,8 @@ interface MobileIconInteractor {
* 1. The default network name, if one is configured
* 2. A derived name based off of the intent [ACTION_SERVICE_PROVIDERS_UPDATED]
* 3. Or, in the case where the repository sends us the default network name, we check for an
- * override in [connectionInfo.operatorAlphaShort], a value that is derived from [ServiceState]
+ * override in [connectionInfo.operatorAlphaShort], a value that is derived from
+ * [ServiceState]
*/
val networkName: StateFlow<NetworkNameModel>
@@ -132,11 +134,9 @@ class MobileIconInteractorImpl(
override val isForceHidden: Flow<Boolean>,
connectionRepository: MobileConnectionRepository,
) : MobileIconInteractor {
- private val connectionInfo = connectionRepository.connectionInfo
-
override val tableLogBuffer: TableLogBuffer = connectionRepository.tableLogBuffer
- override val activity = connectionInfo.mapLatest { it.dataActivityDirection }
+ override val activity = connectionRepository.dataActivityDirection
override val isConnected: Flow<Boolean> = defaultMobileConnectivity.mapLatest { it.isConnected }
@@ -154,11 +154,11 @@ class MobileIconInteractorImpl(
override val isDefaultDataEnabled = defaultSubscriptionHasDataEnabled
override val networkName =
- combine(connectionInfo, connectionRepository.networkName) { connection, networkName ->
- if (
- networkName is NetworkNameModel.Default && connection.operatorAlphaShort != null
- ) {
- NetworkNameModel.IntentDerived(connection.operatorAlphaShort)
+ combine(connectionRepository.operatorAlphaShort, connectionRepository.networkName) {
+ operatorAlphaShort,
+ networkName ->
+ if (networkName is NetworkNameModel.Default && operatorAlphaShort != null) {
+ NetworkNameModel.IntentDerived(operatorAlphaShort)
} else {
networkName
}
@@ -172,19 +172,19 @@ class MobileIconInteractorImpl(
/** Observable for the current RAT indicator icon ([MobileIconGroup]) */
override val networkTypeIconGroup: StateFlow<MobileIconGroup> =
combine(
- connectionInfo,
+ connectionRepository.resolvedNetworkType,
defaultMobileIconMapping,
defaultMobileIconGroup,
isDefault,
- ) { info, mapping, defaultGroup, isDefault ->
+ ) { resolvedNetworkType, mapping, defaultGroup, isDefault ->
if (!isDefault) {
return@combine NOT_DEFAULT_DATA
}
- when (info.resolvedNetworkType) {
+ when (resolvedNetworkType) {
is ResolvedNetworkType.CarrierMergedNetworkType ->
- info.resolvedNetworkType.iconGroupOverride
- else -> mapping[info.resolvedNetworkType.lookupKey] ?: defaultGroup
+ resolvedNetworkType.iconGroupOverride
+ else -> mapping[resolvedNetworkType.lookupKey] ?: defaultGroup
}
}
.distinctUntilChanged()
@@ -199,17 +199,19 @@ class MobileIconInteractorImpl(
}
.stateIn(scope, SharingStarted.WhileSubscribed(), defaultMobileIconGroup.value)
- override val isEmergencyOnly: StateFlow<Boolean> =
- connectionInfo
- .mapLatest { it.isEmergencyOnly }
- .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+ override val isEmergencyOnly = connectionRepository.isEmergencyOnly
override val isRoaming: StateFlow<Boolean> =
- combine(connectionInfo, connectionRepository.cdmaRoaming) { connection, cdmaRoaming ->
- if (connection.carrierNetworkChangeActive) {
+ combine(
+ connectionRepository.carrierNetworkChangeActive,
+ connectionRepository.isGsm,
+ connectionRepository.isRoaming,
+ connectionRepository.cdmaRoaming,
+ ) { carrierNetworkChangeActive, isGsm, isRoaming, cdmaRoaming ->
+ if (carrierNetworkChangeActive) {
false
- } else if (connection.isGsm) {
- connection.isRoaming
+ } else if (isGsm) {
+ isRoaming
} else {
cdmaRoaming
}
@@ -217,12 +219,17 @@ class MobileIconInteractorImpl(
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val level: StateFlow<Int> =
- combine(connectionInfo, alwaysUseCdmaLevel) { connection, alwaysUseCdmaLevel ->
+ combine(
+ connectionRepository.isGsm,
+ connectionRepository.primaryLevel,
+ connectionRepository.cdmaLevel,
+ alwaysUseCdmaLevel,
+ ) { isGsm, primaryLevel, cdmaLevel, alwaysUseCdmaLevel ->
when {
// GSM connections should never use the CDMA level
- connection.isGsm -> connection.primaryLevel
- alwaysUseCdmaLevel -> connection.cdmaLevel
- else -> connection.primaryLevel
+ isGsm -> primaryLevel
+ alwaysUseCdmaLevel -> cdmaLevel
+ else -> primaryLevel
}
}
.stateIn(scope, SharingStarted.WhileSubscribed(), 0)
@@ -235,12 +242,9 @@ class MobileIconInteractorImpl(
)
override val isDataConnected: StateFlow<Boolean> =
- connectionInfo
- .mapLatest { connection -> connection.dataConnectionState == Connected }
+ connectionRepository.dataConnectionState
+ .map { it == Connected }
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
- override val isInService =
- connectionRepository.connectionInfo
- .mapLatest { it.isInService }
- .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+ override val isInService = connectionRepository.isInService
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
index da63ab10f733..075e6ec11ae7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
@@ -22,7 +22,6 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
import java.io.PrintWriter
import javax.inject.Inject
@@ -55,17 +54,14 @@ constructor(
interactor: MobileIconsInteractor,
private val iconController: StatusBarIconController,
private val iconsViewModelFactory: MobileIconsViewModel.Factory,
- private val logger: MobileInputLogger,
+ private val logger: MobileViewLogger,
@Application private val scope: CoroutineScope,
private val statusBarPipelineFlags: StatusBarPipelineFlags,
) : CoreStartable {
private val mobileSubIds: Flow<List<Int>> =
- interactor.filteredSubscriptions
- .mapLatest { subscriptions ->
- subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId }
- }
- .distinctUntilChanged()
- .onEach { logger.logUiAdapterSubIdsUpdated(it) }
+ interactor.filteredSubscriptions.mapLatest { subscriptions ->
+ subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId }
+ }
/**
* We expose the list of tracked subscriptions as a flow of a list of ints, where each int is
@@ -75,7 +71,10 @@ constructor(
* NOTE: this should go away as the view presenter learns more about this data pipeline
*/
private val mobileSubIdsState: StateFlow<List<Int>> =
- mobileSubIds.stateIn(scope, SharingStarted.WhileSubscribed(), listOf())
+ mobileSubIds
+ .distinctUntilChanged()
+ .onEach { logger.logUiAdapterSubIdsUpdated(it) }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), listOf())
/** In order to keep the logs tame, we will reuse the same top-level mobile icons view model */
val mobileIconsViewModel = iconsViewModelFactory.create(mobileSubIdsState)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt
new file mode 100644
index 000000000000..90dff23c637c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.ui
+
+import android.view.View
+import com.android.systemui.Dumpable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.statusbar.pipeline.dagger.MobileViewLog
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
+import java.io.PrintWriter
+import javax.inject.Inject
+
+/** Logs for changes with the new mobile views. */
+@SysUISingleton
+class MobileViewLogger
+@Inject
+constructor(
+ @MobileViewLog private val buffer: LogBuffer,
+ dumpManager: DumpManager,
+) : Dumpable {
+ init {
+ dumpManager.registerNormalDumpable(this)
+ }
+
+ private val collectionStatuses = mutableMapOf<String, Boolean>()
+
+ fun logUiAdapterSubIdsUpdated(subs: List<Int>) {
+ buffer.log(
+ TAG,
+ LogLevel.INFO,
+ { str1 = subs.toString() },
+ { "Sub IDs in MobileUiAdapter updated internally: $str1" },
+ )
+ }
+
+ fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) {
+ buffer.log(
+ TAG,
+ LogLevel.INFO,
+ { str1 = subs.toString() },
+ { "Sub IDs in MobileUiAdapter being sent to icon controller: $str1" },
+ )
+ }
+
+ fun logNewViewBinding(view: View, viewModel: LocationBasedMobileViewModel) {
+ buffer.log(
+ TAG,
+ LogLevel.INFO,
+ {
+ str1 = view.getIdForLogging()
+ str2 = viewModel.getIdForLogging()
+ str3 = viewModel.locationName
+ },
+ { "New view binding. viewId=$str1, viewModelId=$str2, viewModelLocation=$str3" },
+ )
+ }
+
+ fun logCollectionStarted(view: View, viewModel: LocationBasedMobileViewModel) {
+ collectionStatuses[view.getIdForLogging()] = true
+ buffer.log(
+ TAG,
+ LogLevel.INFO,
+ {
+ str1 = view.getIdForLogging()
+ str2 = viewModel.getIdForLogging()
+ str3 = viewModel.locationName
+ },
+ { "Collection started. viewId=$str1, viewModelId=$str2, viewModelLocation=$str3" },
+ )
+ }
+
+ fun logCollectionStopped(view: View, viewModel: LocationBasedMobileViewModel) {
+ collectionStatuses[view.getIdForLogging()] = false
+ buffer.log(
+ TAG,
+ LogLevel.INFO,
+ {
+ str1 = view.getIdForLogging()
+ str2 = viewModel.getIdForLogging()
+ str3 = viewModel.locationName
+ },
+ { "Collection stopped. viewId=$str1, viewModelId=$str2, viewModelLocation=$str3" },
+ )
+ }
+
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
+ pw.println("Collection statuses per view:---")
+ collectionStatuses.forEach { viewId, isCollecting ->
+ pw.println("viewId=$viewId, isCollecting=$isCollecting")
+ }
+ }
+
+ companion object {
+ fun Any.getIdForLogging(): String {
+ // The identityHashCode is guaranteed to be constant for the lifetime of the object.
+ return Integer.toHexString(System.identityHashCode(this))
+ }
+ }
+}
+
+private const val TAG = "MobileViewLogger"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt
new file mode 100644
index 000000000000..f67bc8f14447
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.ui
+
+import android.view.View
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.statusbar.pipeline.dagger.VerboseMobileViewLog
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger.Companion.getIdForLogging
+import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
+import javax.inject.Inject
+
+/**
+ * Logs for **verbose** changes with the new mobile views.
+ *
+ * This is a hopefully temporary log until we resolve some open bugs (b/267236367, b/269565345,
+ * b/270300839).
+ */
+@SysUISingleton
+class VerboseMobileViewLogger
+@Inject
+constructor(
+ @VerboseMobileViewLog private val buffer: LogBuffer,
+) {
+ fun logBinderReceivedSignalIcon(parentView: View, subId: Int, icon: SignalIconModel) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ str1 = parentView.getIdForLogging()
+ int1 = subId
+ int2 = icon.level
+ bool1 = icon.showExclamationMark
+ },
+ {
+ "Binder[subId=$int1, viewId=$str1] received new signal icon: " +
+ "level=$int2 showExclamation=$bool1"
+ },
+ )
+ }
+
+ fun logBinderReceivedNetworkTypeIcon(parentView: View, subId: Int, icon: Icon.Resource?) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ str1 = parentView.getIdForLogging()
+ int1 = subId
+ bool1 = icon != null
+ int2 = icon?.res ?: -1
+ },
+ {
+ "Binder[subId=$int1, viewId=$str1] received new network type icon: " +
+ if (bool1) "resId=$int2" else "null"
+ },
+ )
+ }
+}
+
+private const val TAG = "VerboseMobileViewLogger"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
index db585e68d185..5b7d45b55c5c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
@@ -36,8 +36,10 @@ import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewBinding
+import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
@@ -48,6 +50,7 @@ object MobileIconBinder {
fun bind(
view: ViewGroup,
viewModel: LocationBasedMobileViewModel,
+ logger: MobileViewLogger,
): ModernStatusBarViewBinding {
val mobileGroupView = view.requireViewById<ViewGroup>(R.id.mobile_group)
val activityContainer = view.requireViewById<View>(R.id.inout_container)
@@ -70,8 +73,13 @@ object MobileIconBinder {
val iconTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
val decorTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
+ var isCollecting: Boolean = false
+
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
+ logger.logCollectionStarted(view, viewModel)
+ isCollecting = true
+
launch {
visibilityState.collect { state ->
when (state) {
@@ -96,6 +104,11 @@ object MobileIconBinder {
// Set the icon for the triangle
launch {
viewModel.icon.distinctUntilChanged().collect { icon ->
+ viewModel.verboseLogger?.logBinderReceivedSignalIcon(
+ view,
+ viewModel.subscriptionId,
+ icon,
+ )
mobileDrawable.level =
SignalDrawable.getState(
icon.level,
@@ -114,6 +127,11 @@ object MobileIconBinder {
// Set the network type icon
launch {
viewModel.networkTypeIcon.distinctUntilChanged().collect { dataTypeId ->
+ viewModel.verboseLogger?.logBinderReceivedNetworkTypeIcon(
+ view,
+ viewModel.subscriptionId,
+ dataTypeId,
+ )
dataTypeId?.let { IconViewBinder.bind(dataTypeId, networkTypeView) }
networkTypeView.visibility = if (dataTypeId != null) VISIBLE else GONE
}
@@ -150,6 +168,13 @@ object MobileIconBinder {
}
launch { decorTint.collect { tint -> dotView.setDecorColor(tint) } }
+
+ try {
+ awaitCancellation()
+ } finally {
+ isCollecting = false
+ logger.logCollectionStopped(view, viewModel)
+ }
}
}
@@ -175,6 +200,10 @@ object MobileIconBinder {
}
decorTint.value = newTint
}
+
+ override fun isCollecting(): Boolean {
+ return isCollecting
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileView.kt
index ed9a1884a7b4..4144293d5ccd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileView.kt
@@ -20,6 +20,8 @@ import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import com.android.systemui.R
+import com.android.systemui.statusbar.StatusBarIconView.getVisibleStateString
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconBinder
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
import com.android.systemui.statusbar.pipeline.shared.ui.view.ModernStatusBarView
@@ -31,6 +33,15 @@ class ModernStatusBarMobileView(
var subId: Int = -1
+ override fun toString(): String {
+ return "ModernStatusBarMobileView(" +
+ "slot='$slot', " +
+ "subId=$subId, " +
+ "isCollecting=${binding.isCollecting()}, " +
+ "visibleState=${getVisibleStateString(visibleState)}); " +
+ "viewString=${super.toString()}"
+ }
+
companion object {
/**
@@ -40,6 +51,7 @@ class ModernStatusBarMobileView(
@JvmStatic
fun constructAndBind(
context: Context,
+ logger: MobileViewLogger,
slot: String,
viewModel: LocationBasedMobileViewModel,
): ModernStatusBarMobileView {
@@ -48,7 +60,8 @@ class ModernStatusBarMobileView(
as ModernStatusBarMobileView)
.also {
it.subId = viewModel.subscriptionId
- it.initView(slot) { MobileIconBinder.bind(it, viewModel) }
+ it.initView(slot) { MobileIconBinder.bind(it, viewModel, logger) }
+ logger.logNewViewBinding(it, viewModel)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
index 24cd9304f8dd..f775940140cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
@@ -19,18 +19,23 @@ package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
import android.graphics.Color
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
+import com.android.systemui.statusbar.pipeline.mobile.ui.VerboseMobileViewLogger
/**
* A view model for an individual mobile icon that embeds the notion of a [StatusBarLocation]. This
* allows the mobile icon to change some view parameters at different locations
*
* @param commonImpl for convenience, this class wraps a base interface that can provides all of the
- * common implementations between locations. See [MobileIconViewModel]
+ * common implementations between locations. See [MobileIconViewModel]
+ * @property locationName the name of the location of this VM, used for logging.
+ * @property verboseLogger an optional logger to log extremely verbose view updates.
*/
abstract class LocationBasedMobileViewModel(
val commonImpl: MobileIconViewModelCommon,
statusBarPipelineFlags: StatusBarPipelineFlags,
debugTint: Int,
+ val locationName: String,
+ val verboseLogger: VerboseMobileViewLogger?,
) : MobileIconViewModelCommon by commonImpl {
val useDebugColoring: Boolean = statusBarPipelineFlags.useDebugColoring()
@@ -45,11 +50,16 @@ abstract class LocationBasedMobileViewModel(
fun viewModelForLocation(
commonImpl: MobileIconViewModelCommon,
statusBarPipelineFlags: StatusBarPipelineFlags,
+ verboseMobileViewLogger: VerboseMobileViewLogger,
loc: StatusBarLocation,
): LocationBasedMobileViewModel =
when (loc) {
StatusBarLocation.HOME ->
- HomeMobileIconViewModel(commonImpl, statusBarPipelineFlags)
+ HomeMobileIconViewModel(
+ commonImpl,
+ statusBarPipelineFlags,
+ verboseMobileViewLogger,
+ )
StatusBarLocation.KEYGUARD ->
KeyguardMobileIconViewModel(commonImpl, statusBarPipelineFlags)
StatusBarLocation.QS -> QsMobileIconViewModel(commonImpl, statusBarPipelineFlags)
@@ -60,20 +70,41 @@ abstract class LocationBasedMobileViewModel(
class HomeMobileIconViewModel(
commonImpl: MobileIconViewModelCommon,
statusBarPipelineFlags: StatusBarPipelineFlags,
+ verboseMobileViewLogger: VerboseMobileViewLogger,
) :
MobileIconViewModelCommon,
- LocationBasedMobileViewModel(commonImpl, statusBarPipelineFlags, debugTint = Color.CYAN)
+ LocationBasedMobileViewModel(
+ commonImpl,
+ statusBarPipelineFlags,
+ debugTint = Color.CYAN,
+ locationName = "Home",
+ verboseMobileViewLogger,
+ )
class QsMobileIconViewModel(
commonImpl: MobileIconViewModelCommon,
statusBarPipelineFlags: StatusBarPipelineFlags,
) :
MobileIconViewModelCommon,
- LocationBasedMobileViewModel(commonImpl, statusBarPipelineFlags, debugTint = Color.GREEN)
+ LocationBasedMobileViewModel(
+ commonImpl,
+ statusBarPipelineFlags,
+ debugTint = Color.GREEN,
+ locationName = "QS",
+ // Only do verbose logging for the Home location.
+ verboseLogger = null,
+ )
class KeyguardMobileIconViewModel(
commonImpl: MobileIconViewModelCommon,
statusBarPipelineFlags: StatusBarPipelineFlags,
) :
MobileIconViewModelCommon,
- LocationBasedMobileViewModel(commonImpl, statusBarPipelineFlags, debugTint = Color.MAGENTA)
+ LocationBasedMobileViewModel(
+ commonImpl,
+ statusBarPipelineFlags,
+ debugTint = Color.MAGENTA,
+ locationName = "Keyguard",
+ // Only do verbose logging for the Home location.
+ verboseLogger = null,
+ )
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
index 049627899eff..dbb534b24471 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
@@ -49,7 +49,7 @@ interface MobileIconViewModelCommon {
val contentDescription: Flow<ContentDescription>
val roaming: Flow<Boolean>
/** The RAT icon (LTE, 3G, 5G, etc) to be displayed. Null if we shouldn't show anything */
- val networkTypeIcon: Flow<Icon?>
+ val networkTypeIcon: Flow<Icon.Resource?>
val activityInVisible: Flow<Boolean>
val activityOutVisible: Flow<Boolean>
val activityContainerVisible: Flow<Boolean>
@@ -161,7 +161,7 @@ constructor(
)
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
- override val networkTypeIcon: Flow<Icon?> =
+ override val networkTypeIcon: Flow<Icon.Resource?> =
combine(
iconInteractor.networkTypeIconGroup,
showNetworkTypeIcon,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
index 8cb52af336da..2b90065284d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
@@ -23,6 +23,8 @@ import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
+import com.android.systemui.statusbar.pipeline.mobile.ui.VerboseMobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import javax.inject.Inject
@@ -39,6 +41,8 @@ class MobileIconsViewModel
@Inject
constructor(
val subscriptionIdsFlow: StateFlow<List<Int>>,
+ val logger: MobileViewLogger,
+ private val verboseLogger: VerboseMobileViewLogger,
private val interactor: MobileIconsInteractor,
private val airplaneModeInteractor: AirplaneModeInteractor,
private val constants: ConnectivityConstants,
@@ -66,6 +70,7 @@ constructor(
return LocationBasedMobileViewModel.viewModelForLocation(
common,
statusBarPipelineFlags,
+ verboseLogger,
location,
)
}
@@ -79,6 +84,8 @@ constructor(
class Factory
@Inject
constructor(
+ private val logger: MobileViewLogger,
+ private val verboseLogger: VerboseMobileViewLogger,
private val interactor: MobileIconsInteractor,
private val airplaneModeInteractor: AirplaneModeInteractor,
private val constants: ConnectivityConstants,
@@ -88,6 +95,8 @@ constructor(
fun create(subscriptionIdsFlow: StateFlow<List<Int>>): MobileIconsViewModel {
return MobileIconsViewModel(
subscriptionIdsFlow,
+ logger,
+ verboseLogger,
interactor,
airplaneModeInteractor,
constants,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt
index 6f29e33b5a17..a96e8ff20dd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt
@@ -38,11 +38,24 @@ object LoggerHelper {
int1 = network.getNetId()
str1 = networkCapabilities.toString()
},
- { "onCapabilitiesChanged[default=$bool1]: net=$int1 capabilities=$str1" }
+ { "on${if (bool1) "Default" else ""}CapabilitiesChanged: net=$int1 capabilities=$str1" }
)
}
- fun logOnLost(buffer: LogBuffer, tag: String, network: Network) {
- buffer.log(tag, LogLevel.INFO, { int1 = network.getNetId() }, { "onLost: net=$int1" })
+ fun logOnLost(
+ buffer: LogBuffer,
+ tag: String,
+ network: Network,
+ isDefaultNetworkCallback: Boolean,
+ ) {
+ buffer.log(
+ tag,
+ LogLevel.INFO,
+ {
+ int1 = network.getNetId()
+ bool1 = isDefaultNetworkCallback
+ },
+ { "on${if (bool1) "Default" else ""}Lost: net=$int1" }
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewBinding.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewBinding.kt
index f67876b50233..81f8683411ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewBinding.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewBinding.kt
@@ -37,4 +37,7 @@ interface ModernStatusBarViewBinding {
/** Notifies that the decor tint has been updated (used only for the dot). */
fun onDecorTintChanged(newTint: Int)
+
+ /** Returns true if the binding between the view and view-model is currently collecting. */
+ fun isCollecting(): Boolean
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
index b1e28129a690..1a1340484bfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
@@ -36,7 +36,7 @@ open class ModernStatusBarView(context: Context, attrs: AttributeSet?) :
BaseStatusBarFrameLayout(context, attrs) {
private lateinit var slot: String
- private lateinit var binding: ModernStatusBarViewBinding
+ internal lateinit var binding: ModernStatusBarViewBinding
@StatusBarIconView.VisibleState
private var iconVisibleState: Int = STATE_HIDDEN
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
index e0e0ed795e4a..b1296179d7f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
@@ -41,7 +41,6 @@ import kotlinx.coroutines.flow.stateIn
* or the [WifiRepositoryImpl]'s prod implementation, based on the current demo mode value. In this
* way, downstream clients can all consist of real implementations and not care about which
* repository is responsible for the data. Graphically:
- *
* ```
* RealRepository
* │
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index ee58160a7d3b..b5e7b7a13505 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -128,6 +128,7 @@ constructor(
}
override fun onLost(network: Network) {
+ logger.logOnLost(network, isDefaultNetworkCallback = true)
// The system no longer has a default network, so wifi is definitely not
// default.
trySend(false)
@@ -179,7 +180,7 @@ constructor(
}
override fun onLost(network: Network) {
- logger.logOnLost(network)
+ logger.logOnLost(network, isDefaultNetworkCallback = false)
wifiNetworkChangeEvents.tryEmit(Unit)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
index a32e47592355..bb0b166f7aba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
@@ -48,8 +48,8 @@ constructor(
)
}
- fun logOnLost(network: Network) {
- LoggerHelper.logOnLost(buffer, TAG, network)
+ fun logOnLost(network: Network, isDefaultNetworkCallback: Boolean) {
+ LoggerHelper.logOnLost(buffer, TAG, network, isDefaultNetworkCallback)
}
fun logIntent(intentName: String) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
index 2aff12c8721d..9e8c814ca2a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
@@ -34,6 +34,7 @@ import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarV
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
import kotlinx.coroutines.InternalCoroutinesApi
+import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -74,8 +75,12 @@ object WifiViewBinder {
val iconTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
val decorTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
+ var isCollecting: Boolean = false
+
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
+ isCollecting = true
+
launch {
visibilityState.collect { visibilityState ->
groupView.isVisible = visibilityState == STATE_ICON
@@ -127,6 +132,12 @@ object WifiViewBinder {
airplaneSpacer.isVisible = visible
}
}
+
+ try {
+ awaitCancellation()
+ } finally {
+ isCollecting = false
+ }
}
}
@@ -152,6 +163,10 @@ object WifiViewBinder {
}
decorTint.value = newTint
}
+
+ override fun isCollecting(): Boolean {
+ return isCollecting
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
index 7a734862fe1b..f23e10287164 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
@@ -21,6 +21,7 @@ import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import com.android.systemui.R
+import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.pipeline.shared.ui.view.ModernStatusBarView
import com.android.systemui.statusbar.pipeline.wifi.ui.binder.WifiViewBinder
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
@@ -33,6 +34,15 @@ class ModernStatusBarWifiView(
context: Context,
attrs: AttributeSet?,
) : ModernStatusBarView(context, attrs) {
+
+ override fun toString(): String {
+ return "ModernStatusBarWifiView(" +
+ "slot='$slot', " +
+ "isCollecting=${binding.isCollecting()}, " +
+ "visibleState=${StatusBarIconView.getVisibleStateString(visibleState)}); " +
+ "viewString=${super.toString()}"
+ }
+
companion object {
/**
* Inflates a new instance of [ModernStatusBarWifiView], binds it to a view model, and
@@ -45,12 +55,9 @@ class ModernStatusBarWifiView(
slot: String,
wifiViewModel: LocationBasedWifiViewModel,
): ModernStatusBarWifiView {
- return (
- LayoutInflater.from(context).inflate(R.layout.new_status_bar_wifi_group, null)
- as ModernStatusBarWifiView
- ).also {
- it.initView(slot) { WifiViewBinder.bind(it, wifiViewModel) }
- }
+ return (LayoutInflater.from(context).inflate(R.layout.new_status_bar_wifi_group, null)
+ as ModernStatusBarWifiView)
+ .also { it.initView(slot) { WifiViewBinder.bind(it, wifiViewModel) } }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
index 105723156b50..4b24e7a390e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
@@ -124,7 +124,8 @@ constructor(
isDefault -> icon
wifiConstants.alwaysShowIconIfEnabled -> icon
!connectivityConstants.hasDataCapabilities -> icon
- wifiNetwork is WifiNetworkModel.Active && wifiNetwork.isValidated -> icon
+ // See b/272509965: Even if we have an active and validated wifi network, we
+ // don't want to show the icon if wifi isn't the default network.
else -> WifiIcon.Hidden
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
index 3944c8c77f49..0d09fc184892 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
@@ -21,7 +21,8 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceP
/**
* Controller to cache in process the state of the device provisioning.
* <p>
- * This controller keeps track of the values of device provisioning and user setup complete
+ * This controller keeps track of the values of device provisioning, user setup complete, and
+ * whether Factory Reset Protection is active.
*/
public interface DeviceProvisionedController extends CallbackController<DeviceProvisionedListener> {
@@ -49,6 +50,9 @@ public interface DeviceProvisionedController extends CallbackController<DevicePr
*/
boolean isCurrentUserSetup();
+ /** Returns true when Factory Reset Protection is locking the device. */
+ boolean isFrpActive();
+
/**
* Interface to provide calls when the values tracked change
*/
@@ -69,5 +73,10 @@ public interface DeviceProvisionedController extends CallbackController<DevicePr
* Call when some user changes from not provisioned to provisioned
*/
default void onUserSetupChanged() { }
+
+ /**
+ * Called when the state of FRP changes.
+ */
+ default void onFrpActiveChanged() {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt
index a6b7d9c56900..32c64f457501 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt
@@ -60,9 +60,11 @@ open class DeviceProvisionedControllerImpl @Inject constructor(
}
private val deviceProvisionedUri = globalSettings.getUriFor(Settings.Global.DEVICE_PROVISIONED)
+ private val frpActiveUri = secureSettings.getUriFor(Settings.Secure.SECURE_FRP_MODE)
private val userSetupUri = secureSettings.getUriFor(Settings.Secure.USER_SETUP_COMPLETE)
private val deviceProvisioned = AtomicBoolean(false)
+ private val frpActive = AtomicBoolean(false)
@GuardedBy("lock")
private val userSetupComplete = SparseBooleanArray()
@GuardedBy("lock")
@@ -89,11 +91,15 @@ open class DeviceProvisionedControllerImpl @Inject constructor(
userId: Int
) {
val updateDeviceProvisioned = deviceProvisionedUri in uris
+ val updateFrp = frpActiveUri in uris
val updateUser = if (userSetupUri in uris) userId else NO_USERS
- updateValues(updateDeviceProvisioned, updateUser)
+ updateValues(updateDeviceProvisioned, updateFrp, updateUser)
if (updateDeviceProvisioned) {
onDeviceProvisionedChanged()
}
+ if (updateFrp) {
+ onFrpActiveChanged()
+ }
if (updateUser != NO_USERS) {
onUserSetupChanged()
}
@@ -103,7 +109,7 @@ open class DeviceProvisionedControllerImpl @Inject constructor(
private val userChangedCallback = object : UserTracker.Callback {
@WorkerThread
override fun onUserChanged(newUser: Int, userContext: Context) {
- updateValues(updateDeviceProvisioned = false, updateUser = newUser)
+ updateValues(updateDeviceProvisioned = false, updateFrp = false, updateUser = newUser)
onUserSwitched()
}
@@ -125,19 +131,27 @@ open class DeviceProvisionedControllerImpl @Inject constructor(
updateValues()
userTracker.addCallback(userChangedCallback, backgroundExecutor)
globalSettings.registerContentObserver(deviceProvisionedUri, observer)
+ globalSettings.registerContentObserver(frpActiveUri, observer)
secureSettings.registerContentObserverForUser(userSetupUri, observer, UserHandle.USER_ALL)
}
@WorkerThread
- private fun updateValues(updateDeviceProvisioned: Boolean = true, updateUser: Int = ALL_USERS) {
+ private fun updateValues(
+ updateDeviceProvisioned: Boolean = true,
+ updateFrp: Boolean = true,
+ updateUser: Int = ALL_USERS
+ ) {
if (updateDeviceProvisioned) {
deviceProvisioned
.set(globalSettings.getInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0)
}
+ if (updateFrp) {
+ frpActive.set(globalSettings.getInt(Settings.Secure.SECURE_FRP_MODE, 0) != 0)
+ }
synchronized(lock) {
if (updateUser == ALL_USERS) {
- val N = userSetupComplete.size()
- for (i in 0 until N) {
+ val n = userSetupComplete.size()
+ for (i in 0 until n) {
val user = userSetupComplete.keyAt(i)
val value = secureSettings
.getIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0, user) != 0
@@ -172,6 +186,10 @@ open class DeviceProvisionedControllerImpl @Inject constructor(
return deviceProvisioned.get()
}
+ override fun isFrpActive(): Boolean {
+ return frpActive.get()
+ }
+
override fun isUserSetup(user: Int): Boolean {
val index = synchronized(lock) {
userSetupComplete.indexOfKey(user)
@@ -196,7 +214,13 @@ open class DeviceProvisionedControllerImpl @Inject constructor(
override fun onDeviceProvisionedChanged() {
dispatchChange(
- DeviceProvisionedController.DeviceProvisionedListener::onDeviceProvisionedChanged
+ DeviceProvisionedController.DeviceProvisionedListener::onDeviceProvisionedChanged
+ )
+ }
+
+ override fun onFrpActiveChanged() {
+ dispatchChange(
+ DeviceProvisionedController.DeviceProvisionedListener::onFrpActiveChanged
)
}
@@ -221,6 +245,7 @@ open class DeviceProvisionedControllerImpl @Inject constructor(
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.println("Device provisioned: ${deviceProvisioned.get()}")
+ pw.println("Factory Reset Protection active: ${frpActive.get()}")
synchronized(lock) {
pw.println("User setup complete: $userSetupComplete")
pw.println("Listeners: $listeners")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
index 7acdaffb48c4..01fabcc8bc1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
@@ -22,13 +22,18 @@ import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_LOCKED
import android.annotation.Nullable;
import android.hardware.devicestate.DeviceStateManager;
import android.os.Trace;
-import android.util.Log;
+import android.util.IndentingPrintWriter;
+
+import androidx.annotation.NonNull;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
+import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
import com.android.systemui.util.wrapper.RotationPolicyWrapper;
+import java.io.PrintWriter;
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -39,19 +44,19 @@ import javax.inject.Inject;
*/
@SysUISingleton
public final class DeviceStateRotationLockSettingController
- implements Listenable, RotationLockController.RotationLockControllerCallback {
-
- private static final String TAG = "DSRotateLockSettingCon";
+ implements Listenable, RotationLockController.RotationLockControllerCallback, Dumpable {
private final RotationPolicyWrapper mRotationPolicyWrapper;
private final DeviceStateManager mDeviceStateManager;
private final Executor mMainExecutor;
private final DeviceStateRotationLockSettingsManager mDeviceStateRotationLockSettingsManager;
+ private final DeviceStateRotationLockSettingControllerLogger mLogger;
// On registration for DeviceStateCallback, we will receive a callback with the current state
// and this will be initialized.
private int mDeviceState = -1;
- @Nullable private DeviceStateManager.DeviceStateCallback mDeviceStateCallback;
+ @Nullable
+ private DeviceStateManager.DeviceStateCallback mDeviceStateCallback;
private DeviceStateRotationLockSettingsManager.DeviceStateRotationLockSettingsListener
mDeviceStateRotationLockSettingsListener;
@@ -60,21 +65,27 @@ public final class DeviceStateRotationLockSettingController
RotationPolicyWrapper rotationPolicyWrapper,
DeviceStateManager deviceStateManager,
@Main Executor executor,
- DeviceStateRotationLockSettingsManager deviceStateRotationLockSettingsManager) {
+ DeviceStateRotationLockSettingsManager deviceStateRotationLockSettingsManager,
+ DeviceStateRotationLockSettingControllerLogger logger,
+ DumpManager dumpManager) {
mRotationPolicyWrapper = rotationPolicyWrapper;
mDeviceStateManager = deviceStateManager;
mMainExecutor = executor;
mDeviceStateRotationLockSettingsManager = deviceStateRotationLockSettingsManager;
+ mLogger = logger;
+ dumpManager.registerDumpable(this);
}
@Override
public void setListening(boolean listening) {
+ mLogger.logListeningChange(listening);
if (listening) {
// Note that this is called once with the initial state of the device, even if there
// is no user action.
mDeviceStateCallback = this::updateDeviceState;
mDeviceStateManager.registerCallback(mMainExecutor, mDeviceStateCallback);
- mDeviceStateRotationLockSettingsListener = () -> readPersistedSetting(mDeviceState);
+ mDeviceStateRotationLockSettingsListener = () ->
+ readPersistedSetting("deviceStateRotationLockChange", mDeviceState);
mDeviceStateRotationLockSettingsManager.registerListener(
mDeviceStateRotationLockSettingsListener);
} else {
@@ -89,35 +100,28 @@ public final class DeviceStateRotationLockSettingController
}
@Override
- public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
- if (mDeviceState == -1) {
- Log.wtf(TAG, "Device state was not initialized.");
+ public void onRotationLockStateChanged(boolean newRotationLocked, boolean affordanceVisible) {
+ int deviceState = mDeviceState;
+ boolean currentRotationLocked = mDeviceStateRotationLockSettingsManager
+ .isRotationLocked(deviceState);
+ mLogger.logRotationLockStateChanged(deviceState, newRotationLocked, currentRotationLocked);
+ if (deviceState == -1) {
return;
}
-
- if (rotationLocked
- == mDeviceStateRotationLockSettingsManager.isRotationLocked(mDeviceState)) {
- Log.v(TAG, "Rotation lock same as the current setting, no need to update.");
+ if (newRotationLocked == currentRotationLocked) {
return;
}
-
- saveNewRotationLockSetting(rotationLocked);
+ saveNewRotationLockSetting(newRotationLocked);
}
private void saveNewRotationLockSetting(boolean isRotationLocked) {
- Log.v(
- TAG,
- "saveNewRotationLockSetting [state="
- + mDeviceState
- + "] [isRotationLocked="
- + isRotationLocked
- + "]");
-
- mDeviceStateRotationLockSettingsManager.updateSetting(mDeviceState, isRotationLocked);
+ int deviceState = mDeviceState;
+ mLogger.logSaveNewRotationLockSetting(isRotationLocked, deviceState);
+ mDeviceStateRotationLockSettingsManager.updateSetting(deviceState, isRotationLocked);
}
private void updateDeviceState(int state) {
- Log.v(TAG, "updateDeviceState [state=" + state + "]");
+ mLogger.logUpdateDeviceState(mDeviceState, state);
if (Trace.isEnabled()) {
Trace.traceBegin(
Trace.TRACE_TAG_APP, "updateDeviceState [state=" + state + "]");
@@ -127,22 +131,26 @@ public final class DeviceStateRotationLockSettingController
return;
}
- readPersistedSetting(state);
+ readPersistedSetting("updateDeviceState", state);
} finally {
Trace.endSection();
}
}
- private void readPersistedSetting(int state) {
+ private void readPersistedSetting(String caller, int state) {
int rotationLockSetting =
mDeviceStateRotationLockSettingsManager.getRotationLockSetting(state);
+ boolean shouldBeLocked = rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_LOCKED;
+ boolean isLocked = mRotationPolicyWrapper.isRotationLocked();
+
+ mLogger.readPersistedSetting(caller, state, rotationLockSetting, shouldBeLocked, isLocked);
+
if (rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_IGNORED) {
// This should not happen. Device states that have an ignored setting, should also
// specify a fallback device state which is not ignored.
// We won't handle this device state. The same rotation lock setting as before should
// apply and any changes to the rotation lock setting will be written for the previous
// valid device state.
- Log.w(TAG, "Missing fallback. Ignoring new device state: " + state);
return;
}
@@ -150,9 +158,18 @@ public final class DeviceStateRotationLockSettingController
mDeviceState = state;
// Update the rotation policy, if needed, for this new device state
- boolean newRotationLockSetting = rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_LOCKED;
- if (newRotationLockSetting != mRotationPolicyWrapper.isRotationLocked()) {
- mRotationPolicyWrapper.setRotationLock(newRotationLockSetting);
+ if (shouldBeLocked != isLocked) {
+ mRotationPolicyWrapper.setRotationLock(shouldBeLocked);
}
}
+
+ @Override
+ public void dump(@NonNull PrintWriter printWriter, @NonNull String[] args) {
+ IndentingPrintWriter pw = new IndentingPrintWriter(printWriter);
+ mDeviceStateRotationLockSettingsManager.dump(pw);
+ pw.println("DeviceStateRotationLockSettingController");
+ pw.increaseIndent();
+ pw.println("mDeviceState: " + mDeviceState);
+ pw.decreaseIndent();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt
new file mode 100644
index 000000000000..aa502bc48149
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt
@@ -0,0 +1,140 @@
+/*
+ * 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.statusbar.policy
+
+import android.content.Context
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_IGNORED
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_LOCKED
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_UNLOCKED
+import com.android.internal.R
+import com.android.systemui.log.dagger.DeviceStateAutoRotationLog
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel.VERBOSE
+import javax.inject.Inject
+
+class DeviceStateRotationLockSettingControllerLogger
+@Inject
+constructor(@DeviceStateAutoRotationLog private val logBuffer: LogBuffer, context: Context) {
+
+ private val foldedStates = context.resources.getIntArray(R.array.config_foldedDeviceStates)
+ private val halfFoldedStates =
+ context.resources.getIntArray(R.array.config_halfFoldedDeviceStates)
+ private val unfoldedStates = context.resources.getIntArray(R.array.config_openDeviceStates)
+
+ fun logListeningChange(listening: Boolean) {
+ logBuffer.log(TAG, VERBOSE, { bool1 = listening }, { "setListening: $bool1" })
+ }
+
+ fun logRotationLockStateChanged(
+ state: Int,
+ newRotationLocked: Boolean,
+ currentRotationLocked: Boolean
+ ) {
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ int1 = state
+ bool1 = newRotationLocked
+ bool2 = currentRotationLocked
+ },
+ {
+ "onRotationLockStateChanged: " +
+ "state=$int1 [${int1.toDevicePostureString()}], " +
+ "newRotationLocked=$bool1, " +
+ "currentRotationLocked=$bool2"
+ }
+ )
+ }
+
+ fun logSaveNewRotationLockSetting(isRotationLocked: Boolean, state: Int) {
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ bool1 = isRotationLocked
+ int1 = state
+ },
+ { "saveNewRotationLockSetting: isRotationLocked=$bool1, state=$int1" }
+ )
+ }
+
+ fun logUpdateDeviceState(currentState: Int, newState: Int) {
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ int1 = currentState
+ int2 = newState
+ },
+ {
+ "updateDeviceState: " +
+ "current=$int1 [${int1.toDevicePostureString()}], " +
+ "new=$int2 [${int2.toDevicePostureString()}]"
+ }
+ )
+ }
+
+ fun readPersistedSetting(
+ caller: String,
+ state: Int,
+ rotationLockSetting: Int,
+ shouldBeLocked: Boolean,
+ isLocked: Boolean
+ ) {
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ str1 = caller
+ int1 = state
+ int2 = rotationLockSetting
+ bool1 = shouldBeLocked
+ bool2 = isLocked
+ },
+ {
+ "readPersistedSetting: " +
+ "caller=$str1, " +
+ "state=$int1 [${int1.toDevicePostureString()}], " +
+ "rotationLockSettingForState: ${int2.toRotationLockSettingString()}, " +
+ "shouldBeLocked=$bool1, " +
+ "isLocked=$bool2"
+ }
+ )
+ }
+
+ private fun Int.toDevicePostureString(): String {
+ return when (this) {
+ in foldedStates -> "Folded"
+ in unfoldedStates -> "Unfolded"
+ in halfFoldedStates -> "Half-Folded"
+ -1 -> "Uninitialized"
+ else -> "Unknown"
+ }
+ }
+}
+
+private fun Int.toRotationLockSettingString(): String {
+ return when (this) {
+ DEVICE_STATE_ROTATION_LOCK_IGNORED -> "IGNORED"
+ DEVICE_STATE_ROTATION_LOCK_LOCKED -> "LOCKED"
+ DEVICE_STATE_ROTATION_LOCK_UNLOCKED -> "UNLOCKED"
+ else -> "Unknown"
+ }
+}
+
+private const val TAG = "DSRotateLockSettingCon"
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 bdb656b9d2d5..1e223b1920ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
@@ -146,7 +146,7 @@ constructor(
*
* @param guestUserId id of the guest user to remove
* @param targetUserId id of the user to switch to after guest is removed. If
- * `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
+ * `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
*/
fun removeGuestUser(guestUserId: Int, targetUserId: Int) {
userInteractor.removeGuestUser(
@@ -160,9 +160,9 @@ constructor(
*
* @param guestUserId user id of the guest user to exit
* @param targetUserId user id of the guest user to exit, set to UserHandle#USER_NULL when
- * target user id is not known
+ * target user id is not known
* @param forceRemoveGuestOnExit true: remove guest before switching user, false: remove guest
- * only if its ephemeral, else keep guest
+ * only if its ephemeral, else keep guest
*/
fun exitGuestUser(guestUserId: Int, targetUserId: Int, forceRemoveGuestOnExit: Boolean) {
userInteractor.exitGuestUser(guestUserId, targetUserId, forceRemoveGuestOnExit)
diff --git a/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt b/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
index e092f01d19f6..8e2b05cd9526 100644
--- a/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
@@ -66,7 +66,7 @@ class SwitchToManagedProfileForCallActivity : AlertActivity(), DialogInterface.O
private fun switchToManagedProfile() {
try {
applicationContext.startActivityAsUser(
- Intent(Intent.ACTION_DIAL, phoneNumber),
+ Intent(Intent.ACTION_CALL, phoneNumber),
ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle(),
UserHandle.of(managedProfileUserId)
)
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
index 1065d3349930..59122aff7f21 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
@@ -274,6 +274,7 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
it.title = newInfo.windowTitle
}
newView.keepScreenOn = true
+ logger.logViewAddedToWindowManager(displayInfo.info, newView)
windowManager.addView(newView, paramsWithTitle)
animateViewIn(newView)
}
@@ -286,6 +287,11 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
val view = checkNotNull(currentDisplayInfo.view) {
"First item in activeViews list must have a valid view"
}
+ logger.logViewRemovedFromWindowManager(
+ currentDisplayInfo.info,
+ view,
+ isReinflation = true,
+ )
windowManager.removeView(view)
inflateAndUpdateView(currentDisplayInfo)
}
@@ -294,6 +300,10 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
override fun onDensityOrFontScaleChanged() {
reinflateView()
}
+
+ override fun onThemeChanged() {
+ reinflateView()
+ }
}
private fun addCallbacks() {
@@ -378,6 +388,7 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
}
displayInfo.view = null // Need other places??
animateViewOut(view, removalReason) {
+ logger.logViewRemovedFromWindowManager(displayInfo.info, view)
windowManager.removeView(view)
displayInfo.wakeLock?.release(displayInfo.info.wakeReason)
}
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
index 899b0c2b0947..667e22a82a2a 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
@@ -16,6 +16,7 @@
package com.android.systemui.temporarydisplay
+import android.view.View
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
@@ -141,4 +142,46 @@ open class TemporaryViewLogger<T : TemporaryViewInfo>(
{ "Removal of view with id=$str2 is ignored because $str1" }
)
}
+
+ fun logViewAddedToWindowManager(info: T, view: View) {
+ buffer.log(
+ tag,
+ LogLevel.DEBUG,
+ {
+ str1 = info.id
+ str2 = info.windowTitle
+ str3 = view.javaClass.name
+ int1 = view.getIdForLogging()
+ },
+ {
+ "Adding view to window manager. " +
+ "id=$str1 window=$str2 view=$str3(id=${Integer.toHexString(int1)})"
+ }
+ )
+ }
+
+ fun logViewRemovedFromWindowManager(info: T, view: View, isReinflation: Boolean = false) {
+ buffer.log(
+ tag,
+ LogLevel.DEBUG,
+ {
+ str1 = info.id
+ str2 = info.windowTitle
+ str3 = view.javaClass.name
+ int1 = view.getIdForLogging()
+ bool1 = isReinflation
+ },
+ {
+ "Removing view from window manager${if (bool1) " due to reinflation" else ""}. " +
+ "id=$str1 window=$str2 view=$str3(id=${Integer.toHexString(int1)})"
+ }
+ )
+ }
+
+ companion object {
+ private fun View.getIdForLogging(): Int {
+ // The identityHashCode is guaranteed to be constant for the lifetime of the object.
+ return System.identityHashCode(this)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
index 60241a9684d9..cf0184f9e1ae 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
@@ -27,7 +27,7 @@ import com.android.systemui.util.ViewController
* pass through to the window below.
*
* @param touchableRegionSetter a function that, given the view and an out rect, fills the rect with
- * the touchable region of this view.
+ * the touchable region of this view.
*/
class TouchableRegionViewController(
view: View,
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
index 01a81deabc95..16123882046c 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
@@ -35,7 +35,7 @@ open class ChipbarAnimator @Inject constructor() {
* Animates [innerView] and its children into view.
*
* @return true if the animation was successfully started and false if the animation can't be
- * run for any reason.
+ * run for any reason.
*
* See [ViewHierarchyAnimator.animateAddition].
*/
@@ -55,7 +55,7 @@ open class ChipbarAnimator @Inject constructor() {
* Animates [innerView] and its children out of view.
*
* @return true if the animation was successfully started and false if the animation can't be
- * run for any reason.
+ * run for any reason.
*
* See [ViewHierarchyAnimator.animateRemoval].
*/
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
index fe46318daa30..125cc761d400 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
@@ -28,10 +28,10 @@ import com.android.systemui.temporarydisplay.ViewPriority
* A container for all the state needed to display a chipbar via [ChipbarCoordinator].
*
* @property startIcon the icon to display at the start of the chipbar (on the left in LTR locales;
- * on the right in RTL locales).
+ * on the right in RTL locales).
* @property text the text to display.
* @property endItem an optional end item to display at the end of the chipbar (on the right in LTR
- * locales; on the left in RTL locales).
+ * locales; on the left in RTL locales).
* @property vibrationEffect an optional vibration effect when the chipbar is displayed
* @property allowSwipeToDismiss true if users are allowed to swipe up to dismiss this chipbar.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index b23d870fb82f..8cfe2eac3d33 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -42,7 +42,7 @@ import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.demomode.DemoModeController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -68,7 +68,7 @@ public class TunerServiceImpl extends TunerService {
// Things that use the tunable infrastructure but are now real user settings and
// shouldn't be reset with tuner settings.
private static final String[] RESET_EXCEPTION_LIST = new String[] {
- QSTileHost.TILES_SETTING,
+ QSHost.TILES_SETTING,
Settings.Secure.DOZE_ALWAYS_ON,
Settings.Secure.MEDIA_CONTROLS_RESUME,
Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index 82200c61eeb5..360fc90a2d24 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -53,6 +53,7 @@ import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.events.StatusBarEventsModule;
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.DozeServiceHost;
@@ -93,6 +94,7 @@ import dagger.multibindings.IntoSet;
PowerModule.class,
QSModule.class,
ReferenceScreenshotModule.class,
+ StatusBarEventsModule.class,
VolumeModule.class,
}
)
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
index 2683971f852c..981f429d1f8f 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
@@ -61,8 +61,6 @@ class FoldStateLoggingProviderImpl(
foldStateProvider.stop()
}
- override fun onHingeAngleUpdate(angle: Float) {}
-
override fun onFoldUpdate(@FoldUpdate update: Int) {
val now = clock.elapsedRealtime()
when (update) {
@@ -77,6 +75,10 @@ class FoldStateLoggingProviderImpl(
}
}
+ override fun onUnfoldedScreenAvailable() {
+ Log.d(TAG, "Unfolded screen available")
+ }
+
private fun dispatchState(@LoggedFoldedStates current: Int) {
val now = clock.elapsedRealtime()
val previous = lastState
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
index d5d3efd78d13..3a7ac9c8a8bd 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
@@ -31,6 +31,9 @@ import android.view.WindowManager;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+import javax.inject.Inject;
/**
* If the attached USB accessory has a URL associated with it, and that URL is valid,
@@ -46,13 +49,27 @@ public class UsbAccessoryUriActivity extends AlertActivity
private UsbAccessory mAccessory;
private Uri mUri;
+ private final DeviceProvisionedController mDeviceProvisionedController;
+
+ @Inject
+ UsbAccessoryUriActivity(DeviceProvisionedController deviceProvisionedController) {
+ mDeviceProvisionedController = deviceProvisionedController;
+ }
+
@Override
public void onCreate(Bundle icicle) {
- getWindow().addSystemFlags(
+ getWindow().addSystemFlags(
WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
- super.onCreate(icicle);
+ super.onCreate(icicle);
+
+ // Don't show this dialog during Setup Wizard
+ if (!mDeviceProvisionedController.isDeviceProvisioned()) {
+ Log.e(TAG, "device not provisioned");
+ finish();
+ return;
+ }
- Intent intent = getIntent();
+ Intent intent = getIntent();
mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
String uriString = intent.getStringExtra("uri");
mUri = (uriString == null ? null : Uri.parse(uriString));
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 ad1e5fe08619..b2b7c0b8056f 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
@@ -17,11 +17,8 @@
package com.android.systemui.user.data.repository
-import android.app.IActivityManager
-import android.app.UserSwitchObserver
import android.content.Context
import android.content.pm.UserInfo
-import android.os.IRemoteCallback
import android.os.UserHandle
import android.os.UserManager
import android.provider.Settings
@@ -118,7 +115,6 @@ constructor(
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val globalSettings: GlobalSettings,
private val tracker: UserTracker,
- private val activityManager: IActivityManager,
featureFlags: FeatureFlags,
) : UserRepository {
@@ -203,18 +199,18 @@ constructor(
private fun observeUserSwitching() {
conflatedCallbackFlow {
val callback =
- object : UserSwitchObserver() {
- override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback) {
+ object : UserTracker.Callback {
+ override fun onUserChanging(newUser: Int, userContext: Context) {
trySendWithFailureLogging(true, TAG, "userSwitching started")
}
- override fun onUserSwitchComplete(newUserId: Int) {
+ override fun onUserChanged(newUserId: Int, userContext: Context) {
trySendWithFailureLogging(false, TAG, "userSwitching completed")
}
}
- activityManager.registerUserSwitchObserver(callback, TAG)
+ tracker.addCallback(callback, mainDispatcher.asExecutor())
trySendWithFailureLogging(false, TAG, "initial value defaulting to false")
- awaitClose { activityManager.unregisterUserSwitchObserver(callback) }
+ awaitClose { tracker.removeCallback(callback) }
}
.onEach { _isUserSwitchingInProgress.value = it }
// TODO (b/262838215), Make this stateIn and initialize directly in field declaration
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
index 208061433325..42cd5bca376d 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
@@ -297,7 +297,7 @@ constructor(
* to create a new one.
*
* @return The multi-user user ID of the newly created guest user, or [UserHandle.USER_NULL] if
- * the guest couldn't be created.
+ * the guest couldn't be created.
*/
@UserIdInt
private suspend fun createInBackground(): Int {
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 3f895ad0b5b4..02d447976746 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
@@ -32,6 +32,8 @@ import android.os.UserManager
import android.provider.Settings
import android.util.Log
import com.android.internal.util.UserIcons
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.R
import com.android.systemui.SystemUISecondaryUserService
import com.android.systemui.animation.Expandable
@@ -90,6 +92,7 @@ constructor(
@Application private val applicationScope: CoroutineScope,
telephonyInteractor: TelephonyInteractor,
broadcastDispatcher: BroadcastDispatcher,
+ keyguardUpdateMonitor: KeyguardUpdateMonitor,
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val activityManager: ActivityManager,
private val refreshUsersScheduler: RefreshUsersScheduler,
@@ -286,6 +289,12 @@ constructor(
val isSimpleUserSwitcher: Boolean
get() = repository.isSimpleUserSwitcher()
+ val keyguardUpdateMonitorCallback =
+ object : KeyguardUpdateMonitorCallback() {
+ override fun onKeyguardGoingAway() {
+ dismissDialog()
+ }
+ }
init {
refreshUsersScheduler.refreshIfNotPaused()
@@ -316,6 +325,7 @@ constructor(
onBroadcastReceived(intent, previousSelectedUser)
}
.launchIn(applicationScope)
+ keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
}
fun addCallback(callback: UserCallback) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java
index 81ae6e851fb9..c72853ef37be 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java
@@ -115,6 +115,17 @@ public abstract class SysUIConcurrencyModule {
}
/**
+ * Provide a Long running Executor.
+ */
+ @Provides
+ @SysUISingleton
+ @LongRunning
+ public static DelayableExecutor provideLongRunningDelayableExecutor(
+ @LongRunning Looper looper) {
+ return new ExecutorImpl(looper);
+ }
+
+ /**
* Provide a Background-Thread Executor.
*/
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java b/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java
index 064c224b0568..c6da55c1e20a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java
+++ b/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java
@@ -119,11 +119,11 @@ public class ObservableServiceConnection<T> implements ServiceConnection {
/**
* Default constructor for {@link ObservableServiceConnection}.
- * @param context The context from which the service will be bound with.
+ * @param context The context from which the service will be bound with.
* @param serviceIntent The intent to bind service with.
- * @param executor The executor for connection callbacks to be delivered on
- * @param transformer A {@link ServiceTransformer} for transforming the resulting service
- * into a desired type.
+ * @param executor The executor for connection callbacks to be delivered on
+ * @param transformer A {@link ServiceTransformer} for transforming the resulting service
+ * into a desired type.
*/
@Inject
public ObservableServiceConnection(Context context, Intent serviceIntent,
@@ -143,7 +143,13 @@ public class ObservableServiceConnection<T> implements ServiceConnection {
* @return {@code true} if initiating binding succeed, {@code false} otherwise.
*/
public boolean bind() {
- final boolean bindResult = mContext.bindService(mServiceIntent, mFlags, mExecutor, this);
+ boolean bindResult = false;
+ try {
+ bindResult = mContext.bindService(mServiceIntent, mFlags, mExecutor, this);
+ } catch (SecurityException e) {
+ Log.d(TAG, "Could not bind to service", e);
+ mContext.unbindService(this);
+ }
mBoundCalled = true;
if (DEBUG) {
Log.d(TAG, "bind. bound:" + bindResult);
@@ -197,7 +203,7 @@ public class ObservableServiceConnection<T> implements ServiceConnection {
Log.d(TAG, "removeCallback:" + callback);
}
- mExecutor.execute(()-> mCallbacks.removeIf(el -> el.get() == callback));
+ mExecutor.execute(() -> mCallbacks.removeIf(el-> el.get() == callback));
}
private void onDisconnected(@DisconnectReason int reason) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 52eef421eb8c..1cfcf8cbbdcb 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -1398,6 +1398,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
@Override
public void onAnimationCancel(@NonNull Animator animation) {
mInteractionJankMonitor.cancel(CUJ_VOLUME_CONTROL);
+ Log.d(TAG, "onAnimationCancel");
}
@Override
@@ -1471,6 +1472,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
mHandler.removeMessages(H.DISMISS);
mHandler.removeMessages(H.SHOW);
if (mIsAnimatingDismiss) {
+ Log.d(TAG, "dismissH: isAnimatingDismiss");
+ Trace.endSection();
return;
}
mIsAnimatingDismiss = true;
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
index 8b925b7ad312..b962148b79dc 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
@@ -35,7 +35,7 @@ import android.view.WindowManager;
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.LongRunning;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -61,17 +61,16 @@ public class ImageWallpaper extends WallpaperService {
private final UserTracker mUserTracker;
// used for most tasks (call canvas.drawBitmap, load/unload the bitmap)
- @Background
- private final DelayableExecutor mBackgroundExecutor;
+ @LongRunning
+ private final DelayableExecutor mLongExecutor;
// wait at least this duration before unloading the bitmap
private static final int DELAY_UNLOAD_BITMAP = 2000;
@Inject
- public ImageWallpaper(@Background DelayableExecutor backgroundExecutor,
- UserTracker userTracker) {
+ public ImageWallpaper(@LongRunning DelayableExecutor longExecutor, UserTracker userTracker) {
super();
- mBackgroundExecutor = backgroundExecutor;
+ mLongExecutor = longExecutor;
mUserTracker = userTracker;
}
@@ -105,7 +104,7 @@ public class ImageWallpaper extends WallpaperService {
setFixedSizeAllowed(true);
setShowForAllUsers(true);
mWallpaperLocalColorExtractor = new WallpaperLocalColorExtractor(
- mBackgroundExecutor,
+ mLongExecutor,
new WallpaperLocalColorExtractor.WallpaperLocalColorExtractorCallback() {
@Override
public void onColorsProcessed(List<RectF> regions,
@@ -202,7 +201,7 @@ public class ImageWallpaper extends WallpaperService {
}
private void drawFrame() {
- mBackgroundExecutor.execute(this::drawFrameSynchronized);
+ mLongExecutor.execute(this::drawFrameSynchronized);
}
private void drawFrameSynchronized() {
@@ -257,7 +256,7 @@ public class ImageWallpaper extends WallpaperService {
}
private void unloadBitmapIfNotUsed() {
- mBackgroundExecutor.execute(this::unloadBitmapIfNotUsedSynchronized);
+ mLongExecutor.execute(this::unloadBitmapIfNotUsedSynchronized);
}
private void unloadBitmapIfNotUsedSynchronized() {
@@ -341,7 +340,7 @@ public class ImageWallpaper extends WallpaperService {
* - the mini bitmap from color extractor is recomputed
* - the DELAY_UNLOAD_BITMAP has passed
*/
- mBackgroundExecutor.executeDelayed(
+ mLongExecutor.executeDelayed(
this::unloadBitmapIfNotUsedSynchronized, DELAY_UNLOAD_BITMAP);
}
// even if the bitmap cannot be loaded, call reportEngineShown
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java b/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
index 988fd710d2dc..1e8446f8df1d 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
@@ -29,7 +29,7 @@ import android.util.MathUtils;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.LongRunning;
import com.android.systemui.util.Assert;
import java.io.FileDescriptor;
@@ -66,8 +66,8 @@ public class WallpaperLocalColorExtractor {
private final List<RectF> mPendingRegions = new ArrayList<>();
private final Set<RectF> mProcessedRegions = new ArraySet<>();
- @Background
- private final Executor mBackgroundExecutor;
+ @LongRunning
+ private final Executor mLongExecutor;
private final WallpaperLocalColorExtractorCallback mWallpaperLocalColorExtractorCallback;
@@ -101,13 +101,13 @@ public class WallpaperLocalColorExtractor {
/**
* Creates a new color extractor.
- * @param backgroundExecutor the executor on which the color extraction will be performed
+ * @param longExecutor the executor on which the color extraction will be performed
* @param wallpaperLocalColorExtractorCallback an interface to handle the callbacks from
* the color extractor.
*/
- public WallpaperLocalColorExtractor(@Background Executor backgroundExecutor,
+ public WallpaperLocalColorExtractor(@LongRunning Executor longExecutor,
WallpaperLocalColorExtractorCallback wallpaperLocalColorExtractorCallback) {
- mBackgroundExecutor = backgroundExecutor;
+ mLongExecutor = longExecutor;
mWallpaperLocalColorExtractorCallback = wallpaperLocalColorExtractorCallback;
}
@@ -117,7 +117,7 @@ public class WallpaperLocalColorExtractor {
* not recomputed.
*/
public void setDisplayDimensions(int displayWidth, int displayHeight) {
- mBackgroundExecutor.execute(() ->
+ mLongExecutor.execute(() ->
setDisplayDimensionsSynchronized(displayWidth, displayHeight));
}
@@ -144,7 +144,7 @@ public class WallpaperLocalColorExtractor {
* @param bitmap the new wallpaper
*/
public void onBitmapChanged(@NonNull Bitmap bitmap) {
- mBackgroundExecutor.execute(() -> onBitmapChangedSynchronized(bitmap));
+ mLongExecutor.execute(() -> onBitmapChangedSynchronized(bitmap));
}
private void onBitmapChangedSynchronized(@NonNull Bitmap bitmap) {
@@ -167,7 +167,7 @@ public class WallpaperLocalColorExtractor {
* @param pages the total number of pages of the launcher
*/
public void onPageChanged(int pages) {
- mBackgroundExecutor.execute(() -> onPageChangedSynchronized(pages));
+ mLongExecutor.execute(() -> onPageChangedSynchronized(pages));
}
private void onPageChangedSynchronized(int pages) {
@@ -194,7 +194,7 @@ public class WallpaperLocalColorExtractor {
*/
public void addLocalColorsAreas(@NonNull List<RectF> regions) {
if (regions.size() > 0) {
- mBackgroundExecutor.execute(() -> addLocalColorsAreasSynchronized(regions));
+ mLongExecutor.execute(() -> addLocalColorsAreasSynchronized(regions));
} else {
Log.w(TAG, "Attempt to add colors with an empty list");
}
@@ -218,7 +218,7 @@ public class WallpaperLocalColorExtractor {
* @param regions The areas of interest in our wallpaper (in screen pixel coordinates)
*/
public void removeLocalColorAreas(@NonNull List<RectF> regions) {
- mBackgroundExecutor.execute(() -> removeLocalColorAreasSynchronized(regions));
+ mLongExecutor.execute(() -> removeLocalColorAreasSynchronized(regions));
}
private void removeLocalColorAreasSynchronized(@NonNull List<RectF> regions) {
@@ -236,7 +236,7 @@ public class WallpaperLocalColorExtractor {
* Clean up the memory (in particular, the mini bitmap) used by this class.
*/
public void cleanUp() {
- mBackgroundExecutor.execute(this::cleanUpSynchronized);
+ mLongExecutor.execute(this::cleanUpSynchronized);
}
private void cleanUpSynchronized() {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index 5d896cbbdab4..56df3e114c0b 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -25,7 +25,6 @@ import static android.service.notification.NotificationListenerService.REASON_GR
import static android.service.notification.NotificationStats.DISMISSAL_BUBBLE;
import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
-import static com.android.systemui.flags.Flags.WM_BUBBLE_BAR;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
@@ -358,7 +357,6 @@ public class BubblesManager {
});
}
};
- mBubbles.setBubbleBarEnabled(featureFlags.isEnabled(WM_BUBBLE_BAR));
mBubbles.setSysuiProxy(mSysuiProxy);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
new file mode 100644
index 000000000000..30fed0b0316f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
@@ -0,0 +1,112 @@
+/*
+ * 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.keyguard
+
+import android.app.ActivityTaskManager
+import android.content.pm.PackageManager
+import android.os.PowerManager
+import android.telecom.TelecomManager
+import android.telephony.TelephonyManager
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.shade.ShadeController
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class EmergencyButtonControllerTest : SysuiTestCase() {
+ lateinit var underTest: EmergencyButtonController
+ @Mock lateinit var emergencyButton: EmergencyButton
+ @Mock lateinit var configurationController: ConfigurationController
+ @Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Mock lateinit var telephonyManager: TelephonyManager
+ @Mock lateinit var powerManager: PowerManager
+ @Mock lateinit var activityTaskManager: ActivityTaskManager
+ @Mock lateinit var shadeController: ShadeController
+ @Mock lateinit var telecomManager: TelecomManager
+ @Mock lateinit var metricsLogger: MetricsLogger
+ @Mock lateinit var lockPatternUtils: LockPatternUtils
+ @Mock lateinit var packageManager: PackageManager
+ val fakeSystemClock = FakeSystemClock()
+ val mainExecutor = FakeExecutor(fakeSystemClock)
+ val backgroundExecutor = FakeExecutor(fakeSystemClock)
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ underTest =
+ EmergencyButtonController(
+ emergencyButton,
+ configurationController,
+ keyguardUpdateMonitor,
+ telephonyManager,
+ powerManager,
+ activityTaskManager,
+ shadeController,
+ telecomManager,
+ metricsLogger,
+ lockPatternUtils,
+ mainExecutor,
+ backgroundExecutor
+ )
+ context.setMockPackageManager(packageManager)
+ Mockito.`when`(emergencyButton.context).thenReturn(context)
+ }
+
+ @Test
+ fun testUpdateEmergencyButton() {
+ Mockito.`when`(telecomManager.isInCall).thenReturn(true)
+ Mockito.`when`(lockPatternUtils.isSecure(anyInt())).thenReturn(true)
+ Mockito.`when`(packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY))
+ .thenReturn(true)
+ underTest.updateEmergencyCallButton()
+ backgroundExecutor.runAllReady()
+ verify(emergencyButton, never())
+ .updateEmergencyCallButton(
+ /* isInCall= */ any(),
+ /* hasTelephonyRadio= */ any(),
+ /* simLocked= */ any(),
+ /* isSecure= */ any()
+ )
+ mainExecutor.runAllReady()
+ verify(emergencyButton)
+ .updateEmergencyCallButton(
+ /* isInCall= */ eq(true),
+ /* hasTelephonyRadio= */ eq(true),
+ /* simLocked= */ any(),
+ /* isSecure= */ eq(true)
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
index d91279399341..ed928702b981 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
@@ -18,8 +18,10 @@ package com.android.keyguard
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
+import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
+import android.widget.ImageView
import androidx.test.filters.SmallTest
import com.android.internal.util.LatencyTracker
import com.android.internal.widget.LockPatternUtils
@@ -30,6 +32,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
@@ -37,6 +40,7 @@ import org.mockito.Mockito
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
@SmallTest
@@ -76,7 +80,9 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() {
Mockito.`when`(keyguardPasswordView.findViewById<EditText>(R.id.passwordEntry))
.thenReturn(passwordEntry)
`when`(keyguardPasswordView.resources).thenReturn(context.resources)
- keyguardPasswordViewController =
+ `when`(keyguardPasswordView.findViewById<ImageView>(R.id.switch_ime_button))
+ .thenReturn(mock(ImageView::class.java))
+ keyguardPasswordViewController =
KeyguardPasswordViewController(
keyguardPasswordView,
keyguardUpdateMonitor,
@@ -113,6 +119,18 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() {
}
@Test
+ fun onApplyWindowInsetsListener_onApplyWindowInsets() {
+ `when`(keyguardViewController.isBouncerShowing).thenReturn(false)
+ val argumentCaptor = ArgumentCaptor.forClass(View.OnApplyWindowInsetsListener::class.java)
+
+ keyguardPasswordViewController.onViewAttached()
+ verify(keyguardPasswordView).setOnApplyWindowInsetsListener(argumentCaptor.capture())
+ argumentCaptor.value.onApplyWindowInsets(keyguardPasswordView, null)
+
+ verify(keyguardPasswordView).hideKeyboard()
+ }
+
+ @Test
fun testHideKeyboardWhenOnPause() {
keyguardPasswordViewController.onPause()
keyguardPasswordView.post {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index bffbe17fb2eb..4dc4c2cbf93c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -32,11 +32,9 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -44,7 +42,6 @@ import static org.mockito.Mockito.when;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricOverlayConstants;
-import android.hardware.biometrics.BiometricSourceType;
import android.media.AudioManager;
import android.telephony.TelephonyManager;
import android.testing.AndroidTestingRunner;
@@ -53,7 +50,6 @@ import android.testing.TestableResources;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.View;
import android.view.WindowInsetsController;
import android.widget.FrameLayout;
@@ -96,10 +92,8 @@ import java.util.Optional;
@TestableLooper.RunWithLooper()
public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
private static final int TARGET_USER_ID = 100;
-
@Rule
public MockitoRule mRule = MockitoJUnit.rule();
-
@Mock
private KeyguardSecurityContainer mView;
@Mock
@@ -368,134 +362,12 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
}
@Test
- public void onBouncerVisibilityChanged_allConditionsGood_sideFpsHintShown() {
- setupConditionsToEnableSideFpsHint();
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- verify(mSideFpsController, never()).hide(any());
- }
-
- @Test
- public void onBouncerVisibilityChanged_fpsSensorNotRunning_sideFpsHintHidden() {
- setupConditionsToEnableSideFpsHint();
- setFingerprintDetectionRunning(false);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onBouncerVisibilityChanged_withoutSidedSecurity_sideFpsHintHidden() {
- setupConditionsToEnableSideFpsHint();
- setSideFpsHintEnabledFromResources(false);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onBouncerVisibilityChanged_unlockingWithFingerprintNotAllowed_sideFpsHintHidden() {
- setupConditionsToEnableSideFpsHint();
- setUnlockingWithFingerprintAllowed(false);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onBouncerVisibilityChanged_sideFpsHintShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
public void onBouncerVisibilityChanged_resetsScale() {
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE);
-
+ mKeyguardSecurityContainerController.onBouncerVisibilityChanged(false);
verify(mView).resetScale();
}
@Test
- public void onStartingToHide_sideFpsHintShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onStartingToHide();
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onPause_sideFpsHintShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onPause();
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onResume_sideFpsHintShouldBeShown_sideFpsHintShown() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onResume(0);
-
- verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- verify(mSideFpsController, never()).hide(any());
- }
-
- @Test
- public void onResume_sideFpsHintShouldNotBeShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- setSideFpsHintEnabledFromResources(false);
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onResume(0);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
public void showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock() {
// GIVEN the current security method is SimPin
when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
@@ -647,6 +519,38 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
}
@Test
+ public void testWillRunDismissFromKeyguardIsTrue() {
+ ActivityStarter.OnDismissAction action = mock(ActivityStarter.OnDismissAction.class);
+ when(action.willRunAnimationOnKeyguard()).thenReturn(true);
+ mKeyguardSecurityContainerController.setOnDismissAction(action, null /* cancelAction */);
+
+ mKeyguardSecurityContainerController.finish(false /* strongAuth */, 0 /* currentUser */);
+
+ assertThat(mKeyguardSecurityContainerController.willRunDismissFromKeyguard()).isTrue();
+ }
+
+ @Test
+ public void testWillRunDismissFromKeyguardIsFalse() {
+ ActivityStarter.OnDismissAction action = mock(ActivityStarter.OnDismissAction.class);
+ when(action.willRunAnimationOnKeyguard()).thenReturn(false);
+ mKeyguardSecurityContainerController.setOnDismissAction(action, null /* cancelAction */);
+
+ mKeyguardSecurityContainerController.finish(false /* strongAuth */, 0 /* currentUser */);
+
+ assertThat(mKeyguardSecurityContainerController.willRunDismissFromKeyguard()).isFalse();
+ }
+
+ @Test
+ public void testWillRunDismissFromKeyguardIsFalseWhenNoDismissActionSet() {
+ mKeyguardSecurityContainerController.setOnDismissAction(null /* action */,
+ null /* cancelAction */);
+
+ mKeyguardSecurityContainerController.finish(false /* strongAuth */, 0 /* currentUser */);
+
+ assertThat(mKeyguardSecurityContainerController.willRunDismissFromKeyguard()).isFalse();
+ }
+
+ @Test
public void testOnStartingToHide() {
mKeyguardSecurityContainerController.onStartingToHide();
verify(mInputViewController).onStartingToHide();
@@ -719,39 +623,31 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
any(KeyguardSecurityCallback.class));
}
+ @Test
+ public void testSideFpsControllerShow() {
+ mKeyguardSecurityContainerController.updateSideFpsVisibility(/* isVisible= */ true);
+ verify(mSideFpsController).show(
+ SideFpsUiRequestSource.PRIMARY_BOUNCER,
+ BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
+ }
+
+ @Test
+ public void testSideFpsControllerHide() {
+ mKeyguardSecurityContainerController.updateSideFpsVisibility(/* isVisible= */ false);
+ verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
+ }
+
private KeyguardSecurityContainer.SwipeListener getRegisteredSwipeListener() {
mKeyguardSecurityContainerController.onViewAttached();
verify(mView).setSwipeListener(mSwipeListenerArgumentCaptor.capture());
return mSwipeListenerArgumentCaptor.getValue();
}
- private void setupConditionsToEnableSideFpsHint() {
- attachView();
- setSideFpsHintEnabledFromResources(true);
- setFingerprintDetectionRunning(true);
- setUnlockingWithFingerprintAllowed(true);
- }
-
private void attachView() {
mKeyguardSecurityContainerController.onViewAttached();
verify(mKeyguardUpdateMonitor).registerCallback(mKeyguardUpdateMonitorCallback.capture());
}
- private void setFingerprintDetectionRunning(boolean running) {
- when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(running);
- mKeyguardUpdateMonitorCallback.getValue().onBiometricRunningStateChanged(running,
- BiometricSourceType.FINGERPRINT);
- }
-
- private void setSideFpsHintEnabledFromResources(boolean enabled) {
- mTestableResources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer,
- enabled);
- }
-
- private void setUnlockingWithFingerprintAllowed(boolean allowed) {
- when(mKeyguardUpdateMonitor.isUnlockingWithFingerprintAllowed()).thenReturn(allowed);
- }
-
private void setupGetSecurityView() {
when(mKeyguardSecurityViewFlipperController.getSecurityView(
any(), any(KeyguardSecurityCallback.class)))
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 1bbc19931c21..565fc57e81b7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -37,6 +37,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -160,6 +161,29 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
}
@Test
+ public void testOnApplyWindowInsets_disappearAnimation_paddingNotSet() {
+ int paddingBottom = getContext().getResources()
+ .getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin);
+ int imeInsetAmount = paddingBottom + 1;
+ int systemBarInsetAmount = 0;
+ initMode(MODE_DEFAULT);
+
+ Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
+ Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
+
+ WindowInsets insets = new WindowInsets.Builder()
+ .setInsets(ime(), imeInset)
+ .setInsetsIgnoringVisibility(systemBars(), systemBarInset)
+ .build();
+
+ ensureViewFlipperIsMocked();
+ mKeyguardSecurityContainer.startDisappearAnimation(
+ KeyguardSecurityModel.SecurityMode.Password);
+ mKeyguardSecurityContainer.onApplyWindowInsets(insets);
+ assertThat(mKeyguardSecurityContainer.getPaddingBottom()).isNotEqualTo(imeInsetAmount);
+ }
+
+ @Test
public void testDefaultViewMode() {
initMode(MODE_ONE_HANDED);
initMode(MODE_DEFAULT);
@@ -239,9 +263,6 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
assertThat(viewFlipperConstraint.layout.bottomToBottom).isEqualTo(PARENT_ID);
assertThat(userSwitcherConstraint.layout.topToTop).isEqualTo(PARENT_ID);
assertThat(userSwitcherConstraint.layout.bottomToBottom).isEqualTo(PARENT_ID);
- assertThat(userSwitcherConstraint.layout.bottomMargin).isEqualTo(
- getContext().getResources().getDimensionPixelSize(
- R.dimen.bouncer_user_switcher_y_trans));
assertThat(viewFlipperConstraint.layout.horizontalChainStyle).isEqualTo(CHAIN_SPREAD);
assertThat(userSwitcherConstraint.layout.horizontalChainStyle).isEqualTo(CHAIN_SPREAD);
assertThat(viewFlipperConstraint.layout.mHeight).isEqualTo(MATCH_CONSTRAINT);
@@ -376,6 +397,17 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
assertThat(mKeyguardSecurityContainer.getScaleY()).isEqualTo(1);
}
+ @Test
+ public void testDisappearAnimationPassword() {
+ ensureViewFlipperIsMocked();
+ KeyguardPasswordView keyguardPasswordView = mock(KeyguardPasswordView.class);
+ when(mSecurityViewFlipper.getSecurityView()).thenReturn(keyguardPasswordView);
+
+ mKeyguardSecurityContainer
+ .startDisappearAnimation(KeyguardSecurityModel.SecurityMode.Password);
+ verify(keyguardPasswordView).setDisappearAnimationListener(any());
+ }
+
private BackEvent createBackEvent(float touchX, float progress) {
return new BackEvent(0, 0, progress, BackEvent.EDGE_LEFT);
}
@@ -446,4 +478,12 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
mUserSwitcherController, () -> {
}, mFalsingA11yDelegate);
}
+
+ private void ensureViewFlipperIsMocked() {
+ mSecurityViewFlipper = mock(KeyguardSecurityViewFlipper.class);
+ KeyguardPasswordView keyguardPasswordView = mock(KeyguardPasswordView.class);
+ when(mSecurityViewFlipper.getSecurityView()).thenReturn(keyguardPasswordView);
+ mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
+ }
+
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index dfad15d68375..71449145d668 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -26,7 +26,6 @@ import android.testing.AndroidTestingRunner;
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.ClockAnimations;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
@@ -61,8 +60,6 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase {
@Mock
DozeParameters mDozeParameters;
@Mock
- FeatureFlags mFeatureFlags;
- @Mock
ScreenOffAnimationController mScreenOffAnimationController;
@Captor
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor;
@@ -83,7 +80,6 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase {
mKeyguardUpdateMonitor,
mConfigurationController,
mDozeParameters,
- mFeatureFlags,
mScreenOffAnimationController,
mKeyguardLogger);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 6b80494a0c30..4c92eddd66fb 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -55,8 +55,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.IStrongAuthTracker;
import android.app.trust.TrustManager;
@@ -89,7 +87,6 @@ import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
-import android.os.IRemoteCallback;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -147,6 +144,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -230,8 +228,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Mock
private KeyguardUpdateMonitorLogger mKeyguardUpdateMonitorLogger;
@Mock
- private IActivityManager mActivityService;
- @Mock
private SessionTracker mSessionTracker;
@Mock
private UiEventLogger mUiEventLogger;
@@ -268,8 +264,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Before
public void setup() throws RemoteException {
MockitoAnnotations.initMocks(this);
- when(mActivityService.getCurrentUser()).thenReturn(mCurrentUserInfo);
- when(mActivityService.getCurrentUserId()).thenReturn(mCurrentUserId);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
@@ -309,13 +303,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mMockitoSession = ExtendedMockito.mockitoSession()
.spyStatic(SubscriptionManager.class)
- .spyStatic(ActivityManager.class)
.startMocking();
ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
.when(SubscriptionManager::getDefaultSubscriptionId);
KeyguardUpdateMonitor.setCurrentUser(mCurrentUserId);
when(mUserTracker.getUserId()).thenReturn(mCurrentUserId);
- ExtendedMockito.doReturn(mActivityService).when(ActivityManager::getService);
mContext.getOrCreateTestableResources().addOverride(
com.android.systemui.R.integer.config_face_auth_supported_posture,
@@ -603,9 +595,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
mTestableLooper.processAllMessages();
- verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
- anyInt());
- verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
+ verifyFingerprintAuthenticateCall();
+ verifyFingerprintDetectNeverCalled();
}
@Test
@@ -615,24 +606,51 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
mTestableLooper.processAllMessages();
- verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyInt(), anyInt());
- verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
+ verifyFingerprintAuthenticateNeverCalled();
+ verifyFingerprintDetectNeverCalled();
}
@Test
public void testOnlyDetectFingerprint_whenFingerprintUnlockNotAllowed() {
- // Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
- // will trigger updateBiometricListeningState();
- clearInvocations(mFingerprintManager);
- mKeyguardUpdateMonitor.resetBiometricListeningState();
+ givenDetectFingerprintWithClearingFingerprintManagerInvocations();
- when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
- mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
- mTestableLooper.processAllMessages();
+ verifyFingerprintAuthenticateNeverCalled();
+ verifyFingerprintDetectCall();
+ }
- verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt());
- verify(mFingerprintManager).detectFingerprint(any(), any(), anyInt());
+ @Test
+ public void whenDetectFingerprint_biometricDetectCallback() {
+ ArgumentCaptor<FingerprintManager.FingerprintDetectionCallback> fpDetectCallbackCaptor =
+ ArgumentCaptor.forClass(FingerprintManager.FingerprintDetectionCallback.class);
+
+ givenDetectFingerprintWithClearingFingerprintManagerInvocations();
+ verify(mFingerprintManager).detectFingerprint(
+ any(), fpDetectCallbackCaptor.capture(), anyInt());
+ fpDetectCallbackCaptor.getValue().onFingerprintDetected(0, 0, true);
+
+ // THEN verify keyguardUpdateMonitorCallback receives a detect callback
+ // and NO authenticate callbacks
+ verify(mTestCallback).onBiometricDetected(
+ eq(0), eq(BiometricSourceType.FINGERPRINT), eq(true));
+ verify(mTestCallback, never()).onBiometricAuthenticated(
+ anyInt(), any(), anyBoolean());
+ }
+
+ @Test
+ public void whenDetectFace_biometricDetectCallback() {
+ ArgumentCaptor<FaceManager.FaceDetectionCallback> faceDetectCallbackCaptor =
+ ArgumentCaptor.forClass(FaceManager.FaceDetectionCallback.class);
+
+ givenDetectFace();
+ verify(mFaceManager).detectFace(any(), faceDetectCallbackCaptor.capture(), anyInt());
+ faceDetectCallbackCaptor.getValue().onFaceDetected(0, 0, false);
+
+ // THEN verify keyguardUpdateMonitorCallback receives a detect callback
+ // and NO authenticate callbacks
+ verify(mTestCallback).onBiometricDetected(
+ eq(0), eq(BiometricSourceType.FACE), eq(false));
+ verify(mTestCallback, never()).onBiometricAuthenticated(
+ anyInt(), any(), anyBoolean());
}
@Test
@@ -663,7 +681,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
strongAuthNotRequired();
// WHEN fingerprint is locked out
- fingerprintErrorLockedOut();
+ fingerprintErrorTemporaryLockedOut();
// THEN unlocking with face is not allowed
Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
@@ -686,7 +704,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
strongAuthNotRequired();
// WHEN fingerprint is locked out
- fingerprintErrorLockedOut();
+ fingerprintErrorTemporaryLockedOut();
// THEN unlocking with fingerprint is not allowed
Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
@@ -710,7 +728,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
// WHEN fingerprint is locked out
- fingerprintErrorLockedOut();
+ fingerprintErrorTemporaryLockedOut();
// THEN user is NOT considered as "having trust" and bouncer cannot be skipped
Assert.assertFalse(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
@@ -721,7 +739,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
public void testTriesToAuthenticate_whenBouncer() {
setKeyguardBouncerVisibility(true);
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
verify(mFaceManager).isHardwareDetected();
verify(mFaceManager).hasEnrolledTemplates(anyInt());
}
@@ -731,8 +749,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.sendPrimaryBouncerChanged(
/* bouncerIsOrWillBeShowing */ true, /* bouncerFullyShown */ false);
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -740,7 +757,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
keyguardIsVisible();
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+
+ verifyFaceAuthenticateCall();
verify(mUiEventLogger).logWithInstanceIdAndPosition(
eq(FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP),
eq(0),
@@ -756,8 +774,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -768,17 +785,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
public void nofaceDetect_whenStrongAuthRequiredAndBypassUdfpsSupportedAndFpRunning() {
- // GIVEN mocked keyguardUpdateMonitorCallback
- KeyguardUpdateMonitorCallback keyguardUpdateMonitorCallback =
- mock(KeyguardUpdateMonitorCallback.class);
- mKeyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback);
-
// GIVEN bypass is enabled, face detection is supported
lockscreenBypassIsAllowed();
supportsFaceDetection();
@@ -793,32 +804,21 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// THEN face detect and authenticate are NOT triggered
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceDetectNeverCalled();
+ verifyFaceAuthenticateNeverCalled();
// THEN biometric help message sent to callback
- verify(keyguardUpdateMonitorCallback).onBiometricHelp(
+ verify(mTestCallback).onBiometricHelp(
eq(BIOMETRIC_HELP_FACE_NOT_AVAILABLE), anyString(), eq(BiometricSourceType.FACE));
}
@Test
public void faceDetect_whenStrongAuthRequiredAndBypass() {
- // GIVEN bypass is enabled, face detection is supported and strong auth is required
- lockscreenBypassIsAllowed();
- supportsFaceDetection();
- strongAuthRequiredEncrypted();
- keyguardIsVisible();
- // fingerprint is NOT running, UDFPS is NOT supported
-
- // WHEN the device wakes up
- mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
- mTestableLooper.processAllMessages();
+ givenDetectFace();
// FACE detect is triggered, not authenticate
- verify(mFaceManager).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceDetectCall();
+ verifyFaceAuthenticateNeverCalled();
// WHEN bouncer becomes visible
setKeyguardBouncerVisibility(true);
@@ -826,9 +826,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// THEN face scanning is not run
mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
+ verifyFaceAuthenticateNeverCalled();
+ verifyFaceDetectNeverCalled();
}
@Test
@@ -843,9 +842,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// FACE detect and authenticate are NOT triggered
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceDetectNeverCalled();
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -883,7 +881,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
}
@Test
@@ -891,12 +889,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setKeyguardShowing(false, true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
- verify(mFaceManager, never()).authenticate(any(),
- any(),
- any(),
- any(),
- anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -907,15 +900,12 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// THEN fingerprint shouldn't listen
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isFalse();
- verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyInt(), anyInt());
-
+ verifyFingerprintAuthenticateNeverCalled();
// WHEN alternate bouncer is shown
mKeyguardUpdateMonitor.setAlternateBouncerShowing(true);
// THEN make sure FP listening begins
- verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
- anyInt());
+ verifyFingerprintAuthenticateCall();
}
@Test
@@ -927,7 +917,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */,
new ArrayList<>());
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
}
@Test
@@ -935,7 +925,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
mTestableLooper.processAllMessages();
clearInvocations(mFaceManager);
@@ -948,12 +938,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.handleKeyguardReset();
assertThat(mKeyguardUpdateMonitor.isFaceDetectionRunning()).isFalse();
- verify(mFaceManager, never()).authenticate(any(),
- any(),
- any(),
- any(),
- anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -963,8 +948,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */, true /* newlyUnlocked */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */, new ArrayList<>());
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -976,9 +960,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
keyguardIsVisible();
mTestableLooper.processAllMessages();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
+ verifyFaceAuthenticateNeverCalled();
+ verifyFaceDetectNeverCalled();
}
@Test
@@ -987,16 +970,14 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
.onAuthenticationError(FingerprintManager.BIOMETRIC_ERROR_POWER_PRESSED, "");
// THEN doesn't authenticate immediately
- verify(mFingerprintManager, never()).authenticate(any(),
- any(), any(), any(), anyInt(), anyInt(), anyInt());
+ verifyFingerprintAuthenticateNeverCalled();
// WHEN all messages (with delays) are processed
mTestableLooper.moveTimeForward(HAL_POWER_PRESS_TIMEOUT);
mTestableLooper.processAllMessages();
// THEN fingerprint manager attempts to authenticate again
- verify(mFingerprintManager).authenticate(any(),
- any(), any(), any(), anyInt(), anyInt(), anyInt());
+ verifyFingerprintAuthenticateCall();
}
@Test
@@ -1008,8 +989,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
setKeyguardBouncerVisibility(true);
mTestableLooper.processAllMessages();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -1082,11 +1062,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test
public void testBiometricsCleared_whenUserSwitches() throws Exception {
- final IRemoteCallback reply = new IRemoteCallback.Stub() {
- @Override
- public void sendResult(Bundle data) {
- } // do nothing
- };
final BiometricAuthenticated dummyAuthentication =
new BiometricAuthenticated(true /* authenticated */, true /* strong */);
mKeyguardUpdateMonitor.mUserFaceAuthenticated.put(0 /* user */, dummyAuthentication);
@@ -1094,18 +1069,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(1);
assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(1);
- mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, reply);
+ mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, new CountDownLatch(0));
assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(0);
assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(0);
}
@Test
public void testMultiUserJankMonitor_whenUserSwitches() throws Exception {
- final IRemoteCallback reply = new IRemoteCallback.Stub() {
- @Override
- public void sendResult(Bundle data) {
- } // do nothing
- };
mKeyguardUpdateMonitor.handleUserSwitchComplete(10 /* user */);
verify(mInteractionJankMonitor).end(InteractionJankMonitor.CUJ_USER_SWITCH);
verify(mLatencyTracker).onActionEnd(LatencyTracker.ACTION_USER_SWITCH);
@@ -1136,9 +1106,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
- verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
- anyInt());
+ verifyFaceAuthenticateCall();
+ verifyFingerprintAuthenticateCall();
when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser)))
.thenReturn(fingerprintLockoutMode);
@@ -1166,8 +1135,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(fpLocked);
assertThat(mKeyguardUpdateMonitor.isFaceLockedOut()).isEqualTo(faceLocked);
- // Fingerprint should be restarted once its cancelled bc on lockout, the device
- // can still detectFingerprint (and if it's not locked out, fingerprint can listen)
+ // Fingerprint should be cancelled on lockout if going to lockout state, else
+ // restarted if it's not
assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
.isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
}
@@ -1585,10 +1554,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
public void testFaceDoesNotAuth_afterPinAttempt() {
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.setCredentialAttempted();
- verify(mFingerprintManager, never()).authenticate(any(), any(), any(),
- any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -1631,7 +1597,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
// Fingerprint is locked out.
- fingerprintErrorLockedOut();
+ fingerprintErrorTemporaryLockedOut();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@@ -1963,9 +1929,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
- verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
- anyInt());
+ verifyFaceAuthenticateCall();
+ verifyFingerprintAuthenticateCall();
mKeyguardUpdateMonitor.onFaceAuthenticated(0, false);
// Make sure keyguard is going away after face auth attempt, and that it calls
@@ -1991,8 +1956,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchDreamingStopped();
mTestableLooper.processAllMessages();
- verify(mFaceManager, never()).authenticate(
- any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -2005,15 +1969,14 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// THEN face auth isn't triggered
- verify(mFaceManager, never()).authenticate(
- any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
// WHEN device wakes up from the power button
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
// THEN face auth is triggered
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
}
@@ -2184,7 +2147,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
@@ -2217,7 +2180,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
@@ -2236,6 +2199,32 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
}
@Test
+ public void testPostureChangeToUnsupported_stopsFaceListeningState() {
+ // GIVEN device is listening for face
+ mKeyguardUpdateMonitor.mConfigFaceAuthSupportedPosture = DEVICE_POSTURE_CLOSED;
+ deviceInPostureStateClosed();
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+ mTestableLooper.processAllMessages();
+ keyguardIsVisible();
+
+ verifyFaceAuthenticateCall();
+
+ final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
+ mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
+ KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+ mKeyguardUpdateMonitor.registerCallback(callback);
+
+ // WHEN device is opened
+ deviceInPostureStateOpened();
+ mTestableLooper.processAllMessages();
+
+ // THEN face listening is stopped.
+ verify(faceCancel).cancel();
+ verify(callback).onBiometricRunningStateChanged(
+ eq(false), eq(BiometricSourceType.FACE));
+ }
+
+ @Test
public void testShouldListenForFace_withLockedDown_returnsFalse()
throws RemoteException {
keyguardNotGoingAway();
@@ -2443,6 +2432,64 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
eq(false));
}
+ @Test
+ public void detectFingerprint_onTemporaryLockoutReset_authenticateFingerprint() {
+ ArgumentCaptor<FingerprintManager.LockoutResetCallback> fpLockoutResetCallbackCaptor =
+ ArgumentCaptor.forClass(FingerprintManager.LockoutResetCallback.class);
+ verify(mFingerprintManager).addLockoutResetCallback(fpLockoutResetCallbackCaptor.capture());
+
+ // GIVEN device is locked out
+ fingerprintErrorTemporaryLockedOut();
+
+ // GIVEN FP detection is running
+ givenDetectFingerprintWithClearingFingerprintManagerInvocations();
+ verifyFingerprintDetectCall();
+ verifyFingerprintAuthenticateNeverCalled();
+
+ // WHEN temporary lockout resets
+ fpLockoutResetCallbackCaptor.getValue().onLockoutReset(0);
+ mTestableLooper.processAllMessages();
+
+ // THEN fingerprint detect state should cancel & then restart (for authenticate call)
+ assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
+ .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
+ }
+
+ private void verifyFingerprintAuthenticateNeverCalled() {
+ verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
+ anyInt(), anyInt());
+ }
+
+ private void verifyFingerprintAuthenticateCall() {
+ verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
+ anyInt());
+ }
+
+ private void verifyFingerprintDetectNeverCalled() {
+ verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
+ }
+
+ private void verifyFingerprintDetectCall() {
+ verify(mFingerprintManager).detectFingerprint(any(), any(), anyInt());
+ }
+
+ private void verifyFaceAuthenticateNeverCalled() {
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
+ anyBoolean());
+ }
+
+ private void verifyFaceAuthenticateCall() {
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ }
+
+ private void verifyFaceDetectNeverCalled() {
+ verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
+ }
+
+ private void verifyFaceDetectCall() {
+ verify(mFaceManager).detectFace(any(), any(), anyInt());
+ }
+
private void userDeviceLockDown() {
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
when(mStrongAuthTracker.getStrongAuthForUser(mCurrentUserId))
@@ -2512,7 +2559,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setSwitchingUser(true);
}
- private void fingerprintErrorLockedOut() {
+ private void fingerprintErrorTemporaryLockedOut() {
mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
.onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT, "Fingerprint locked out");
}
@@ -2652,6 +2699,30 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
receiver.setPendingResult(pendingResult);
}
+ private void givenDetectFingerprintWithClearingFingerprintManagerInvocations() {
+ // Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
+ // will trigger updateBiometricListeningState();
+ clearInvocations(mFingerprintManager);
+ mKeyguardUpdateMonitor.resetBiometricListeningState();
+
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
+ mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
+ mTestableLooper.processAllMessages();
+ }
+
+ private void givenDetectFace() {
+ // GIVEN bypass is enabled, face detection is supported and strong auth is required
+ lockscreenBypassIsAllowed();
+ supportsFaceDetection();
+ strongAuthRequiredEncrypted();
+ keyguardIsVisible();
+ // fingerprint is NOT running, UDFPS is NOT supported
+
+ // WHEN the device wakes up
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+ mTestableLooper.processAllMessages();
+ }
+
private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
int subscription = simInited
? 1/* mock subid=1 */ : SubscriptionManager.PLACEHOLDER_SUBSCRIPTION_ID_BASE;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
index e9a2789bb5c8..9fe32f1e378b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
@@ -32,6 +32,7 @@ import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.util.Optional
@@ -83,6 +84,33 @@ class ScreenOnCoordinatorTest : SysuiTestCase() {
}
@Test
+ fun testTasksReady_onScreenTurningOnAndTurnedOnEventsCalledTogether_callsDrawnCallback() {
+ screenOnCoordinator.onScreenTurningOn(runnable)
+ screenOnCoordinator.onScreenTurnedOn()
+
+ onUnfoldOverlayReady()
+ onFoldAodReady()
+ waitHandlerIdle(testHandler)
+
+ // Should be called when both unfold overlay and keyguard drawn ready
+ verify(runnable).run()
+ }
+
+ @Test
+ fun testTasksReady_onScreenTurnedOnAndTurnedOffBeforeCompletion_doesNotCallDrawnCallback() {
+ screenOnCoordinator.onScreenTurningOn(runnable)
+ screenOnCoordinator.onScreenTurnedOn()
+ screenOnCoordinator.onScreenTurnedOff()
+
+ onUnfoldOverlayReady()
+ onFoldAodReady()
+ waitHandlerIdle(testHandler)
+
+ // Should not be called because this screen turning on call is not valid anymore
+ verify(runnable, never()).run()
+ }
+
+ @Test
fun testUnfoldTransitionDisabledDrawnTasksReady_onScreenTurningOn_callsDrawnCallback() {
// Recreate with empty unfoldComponent
screenOnCoordinator = ScreenOnCoordinator(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogTest.kt
index 777dd4e0b4a3..ca6f42618e2a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogTest.kt
@@ -19,7 +19,7 @@ import android.os.Handler
import android.provider.Settings
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
-import android.widget.ImageView
+import android.view.ViewGroup
import android.widget.SeekBar
import androidx.test.filters.SmallTest
import com.android.systemui.R
@@ -68,14 +68,14 @@ class FontScalingDialogTest : SysuiTestCase() {
fun progressIsZero_clickIconEnd_seekBarProgressIncreaseOne_fontSizeScaled() {
fontScalingDialog.show()
- val iconEnd: ImageView = fontScalingDialog.findViewById(R.id.icon_end)!!
+ val iconEndFrame: ViewGroup = fontScalingDialog.findViewById(R.id.icon_end_frame)!!
val seekBarWithIconButtonsView: SeekBarWithIconButtonsView =
fontScalingDialog.findViewById(R.id.font_scaling_slider)!!
val seekBar: SeekBar = fontScalingDialog.findViewById(R.id.seekbar)!!
seekBarWithIconButtonsView.setProgress(0)
- iconEnd.performClick()
+ iconEndFrame.performClick()
val currentScale = systemSettings.getFloat(Settings.System.FONT_SCALE, /* def = */ 1.0f)
assertThat(seekBar.getProgress()).isEqualTo(1)
@@ -88,14 +88,14 @@ class FontScalingDialogTest : SysuiTestCase() {
fun progressIsMax_clickIconStart_seekBarProgressDecreaseOne_fontSizeScaled() {
fontScalingDialog.show()
- val iconStart: ImageView = fontScalingDialog.findViewById(R.id.icon_start)!!
+ val iconStartFrame: ViewGroup = fontScalingDialog.findViewById(R.id.icon_start_frame)!!
val seekBarWithIconButtonsView: SeekBarWithIconButtonsView =
fontScalingDialog.findViewById(R.id.font_scaling_slider)!!
val seekBar: SeekBar = fontScalingDialog.findViewById(R.id.seekbar)!!
seekBarWithIconButtonsView.setProgress(fontSizeValueArray.size - 1)
- iconStart.performClick()
+ iconStartFrame.performClick()
val currentScale = systemSettings.getFloat(Settings.System.FONT_SCALE, /* def = */ 1.0f)
assertThat(seekBar.getProgress()).isEqualTo(fontSizeValueArray.size - 2)
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 f01da2dd3a6b..8a5c5b58d058 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
@@ -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' 500, 'ital' 0.5, 'GRAD' 450", interp.lerp(startFont, endFont, 0.5f))
+ assertSameAxes("'wght' 496, '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' 250, 'ital' 0.5", interp.lerp(startFont, endFont, 0.5f))
+ assertSameAxes("'wght' 249, 'ital' 0.5", interp.lerp(startFont, endFont, 0.5f))
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
index bce98cf116d4..05748382534f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
@@ -15,27 +15,49 @@
*/
package com.android.systemui.biometrics
+import android.content.Context
import android.hardware.biometrics.BiometricAuthenticator
+import android.hardware.biometrics.SensorLocationInternal
+import android.hardware.biometrics.SensorProperties
+import android.hardware.display.DisplayManagerGlobal
+import android.hardware.fingerprint.FingerprintManager
+import android.hardware.fingerprint.FingerprintSensorProperties
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.os.Bundle
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
+import android.view.Display
+import android.view.DisplayAdjustments
+import android.view.DisplayInfo
+import android.view.Surface
import android.view.View
+import android.view.ViewGroup
import androidx.test.filters.SmallTest
+import com.airbnb.lottie.LottieAnimationView
import com.android.systemui.R
+import com.android.systemui.biometrics.AuthBiometricView.STATE_AUTHENTICATING_ANIMATING_IN
import com.android.systemui.SysuiTestCase
+import com.android.systemui.SysuiTestableContext
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
+import org.mockito.Mockito.mock
import org.mockito.Mockito.never
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
+import org.mockito.Mockito.`when` as whenEver
+
+private const val DISPLAY_ID = 2
+private const val SENSOR_ID = 1
@RunWith(AndroidTestingRunner::class)
@RunWithLooper(setAsMainLooper = true)
@@ -50,9 +72,22 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
private lateinit var callback: AuthBiometricView.Callback
@Mock
+ private lateinit var fingerprintManager: FingerprintManager
+
+ @Mock
+ private lateinit var iconView: LottieAnimationView
+
+ @Mock
+ private lateinit var iconViewOverlay: LottieAnimationView
+
+ @Mock
+ private lateinit var iconLayoutParamSize: Pair<Int, Int>
+
+ @Mock
private lateinit var panelController: AuthPanelController
private lateinit var biometricView: AuthBiometricView
+ private lateinit var iconController: AuthBiometricFingerprintIconController
private fun createView(allowDeviceCredential: Boolean = false): AuthBiometricFingerprintView {
val view: AuthBiometricFingerprintView =
@@ -277,5 +312,186 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
verify(callback).onAction(AuthBiometricView.Callback.ACTION_USE_DEVICE_CREDENTIAL)
}
+ private fun testWithSfpsDisplay(
+ isReverseDefaultRotation: Boolean = false,
+ inRearDisplayMode: Boolean = false,
+ isFolded: Boolean = false,
+ initInfo: DisplayInfo.() -> Unit = {},
+ block: () -> Unit
+ ) {
+ val displayInfo = DisplayInfo()
+ displayInfo.initInfo()
+
+ val dmGlobal = mock(DisplayManagerGlobal::class.java)
+ val display = Display(dmGlobal, DISPLAY_ID, displayInfo,
+ DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS)
+
+ whenEver(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo)
+
+ val iconControllerContext = context.createDisplayContext(display) as SysuiTestableContext
+ iconControllerContext.orCreateTestableResources.addOverride(
+ com.android.internal.R.bool.config_reverseDefaultRotation,
+ isReverseDefaultRotation
+ )
+
+ val rearDisplayDeviceStates = if (inRearDisplayMode) intArrayOf(3) else intArrayOf()
+ iconControllerContext.orCreateTestableResources.addOverride(
+ com.android.internal.R.array.config_rearDisplayDeviceStates,
+ rearDisplayDeviceStates
+ )
+
+ val layoutParams = mock(ViewGroup.LayoutParams::class.java)
+ whenEver(iconView.layoutParams).thenReturn(layoutParams)
+ whenEver(iconViewOverlay.layoutParams).thenReturn(layoutParams)
+
+ var locations = listOf(SensorLocationInternal("", 2500, 0, 0))
+ whenEver(fingerprintManager.sensorPropertiesInternal)
+ .thenReturn(
+ listOf(
+ FingerprintSensorPropertiesInternal(
+ SENSOR_ID,
+ SensorProperties.STRENGTH_STRONG,
+ 5 /* maxEnrollmentsPerUser */,
+ listOf() /* componentInfo */,
+ FingerprintSensorProperties.TYPE_POWER_BUTTON,
+ true /* halControlsIllumination */,
+ true /* resetLockoutRequiresHardwareAuthToken */,
+ locations
+ )
+ )
+ )
+ iconControllerContext.addMockSystemService(Context.FINGERPRINT_SERVICE, fingerprintManager)
+
+ iconController = AuthBiometricFingerprintIconController(
+ iconControllerContext,
+ iconView,
+ iconViewOverlay
+ )
+ iconController.onFoldUpdated(isFolded)
+
+ biometricView.mIconController = iconController
+ block()
+ }
+
+ @Test
+ fun sfpsRearDisplay_showsCorrectAnimationAssetsAcrossRotations() {
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = true,
+ isFolded = false,
+ { rotation = Surface.ROTATION_0 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = true,
+ isFolded = false,
+ { rotation = Surface.ROTATION_90 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = true,
+ isFolded = false,
+ { rotation = Surface.ROTATION_180 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = true,
+ isFolded = false,
+ { rotation = Surface.ROTATION_270 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ val expectedLottieAssetOrder: List<Int> = listOf(
+ R.raw.biometricprompt_rear_landscape_base,
+ R.raw.biometricprompt_rear_portrait_reverse_base,
+ R.raw.biometricprompt_rear_landscape_base,
+ R.raw.biometricprompt_rear_portrait_base,
+ )
+
+ val lottieAssetCaptor: ArgumentCaptor<Int> = ArgumentCaptor.forClass(Int::class.java)
+ verify(iconView, times(4)).setAnimation(lottieAssetCaptor.capture())
+ val observedLottieAssetOrder: List<Int> = lottieAssetCaptor.getAllValues()
+ assertThat(observedLottieAssetOrder).containsExactlyElementsIn(expectedLottieAssetOrder)
+ .inOrder()
+ }
+
+ @Test
+ fun sfpsDefaultDisplayFolded_showsAnimationsAssetsCorrectlyAcrossRotations() {
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = true,
+ { rotation = Surface.ROTATION_0 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = true,
+ { rotation = Surface.ROTATION_90 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN); }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = true,
+ { rotation = Surface.ROTATION_180 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN); }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = true,
+ { rotation = Surface.ROTATION_270 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN); }
+ val expectedLottieAssetOrder: List<Int> = listOf(
+ R.raw.biometricprompt_folded_base_default,
+ R.raw.biometricprompt_folded_base_topleft,
+ R.raw.biometricprompt_folded_base_default,
+ R.raw.biometricprompt_folded_base_bottomright,
+ )
+
+ val lottieAssetCaptor: ArgumentCaptor<Int> = ArgumentCaptor.forClass(Int::class.java)
+ verify(iconView, times(4)).setAnimation(lottieAssetCaptor.capture())
+ val observedLottieAssetOrder: List<Int> = lottieAssetCaptor.getAllValues()
+ assertThat(observedLottieAssetOrder).containsExactlyElementsIn(expectedLottieAssetOrder)
+ .inOrder()
+ }
+
+ @Test
+ fun sfpsDefaultDisplayUnfolded_showsAnimationsAssetsCorrectlyAcrossRotations() {
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = false,
+ { rotation = Surface.ROTATION_0 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = false,
+ { rotation = Surface.ROTATION_90 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = false,
+ { rotation = Surface.ROTATION_180 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = false,
+ { rotation = Surface.ROTATION_270 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ val expectedLottieAssetOrder: List<Int> = listOf(
+ R.raw.biometricprompt_landscape_base,
+ R.raw.biometricprompt_portrait_base_topleft,
+ R.raw.biometricprompt_landscape_base,
+ R.raw.biometricprompt_portrait_base_bottomright,
+ )
+
+ val lottieAssetCaptor: ArgumentCaptor<Int> = ArgumentCaptor.forClass(Int::class.java)
+ verify(iconView, times(4)).setAnimation(lottieAssetCaptor.capture())
+ val observedLottieAssetOrder: List<Int> = lottieAssetCaptor.getAllValues()
+ assertThat(observedLottieAssetOrder).containsExactlyElementsIn(expectedLottieAssetOrder)
+ .inOrder()
+ }
+
override fun waitForIdleSync() = TestableLooper.get(this).processAllMessages()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
index b765ab3c5eac..6e423593b379 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -17,15 +17,17 @@
package com.android.systemui.biometrics
import android.graphics.Point
-import android.hardware.biometrics.BiometricSourceType
+import android.hardware.biometrics.BiometricSourceType.FACE
+import android.hardware.biometrics.BiometricSourceType.FINGERPRINT
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.keyguard.logging.KeyguardLogger
import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.logcatLogBuffer
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -34,11 +36,11 @@ import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.CentralSurfaces
-import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.leak.RotationUtils
import com.android.systemui.util.mockito.any
+import javax.inject.Provider
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
@@ -48,15 +50,15 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.eq
+import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-import javax.inject.Provider
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -73,7 +75,6 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
- @Mock private lateinit var bypassController: KeyguardBypassController
@Mock private lateinit var biometricUnlockController: BiometricUnlockController
@Mock private lateinit var udfpsControllerProvider: Provider<UdfpsController>
@Mock private lateinit var udfpsController: UdfpsController
@@ -82,10 +83,15 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Mock private lateinit var lightRevealScrim: LightRevealScrim
@Mock private lateinit var fpSensorProp: FingerprintSensorPropertiesInternal
+ @Captor
+ private lateinit var biometricModeListener:
+ ArgumentCaptor<BiometricUnlockController.BiometricModeListener>
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- staticMockSession = mockitoSession()
+ staticMockSession =
+ mockitoSession()
.mockStatic(RotationUtils::class.java)
.strictness(Strictness.LENIENT)
.startMocking()
@@ -94,23 +100,24 @@ class AuthRippleControllerTest : SysuiTestCase() {
`when`(authController.udfpsProps).thenReturn(listOf(fpSensorProp))
`when`(udfpsControllerProvider.get()).thenReturn(udfpsController)
- controller = AuthRippleController(
- mCentralSurfaces,
- context,
- authController,
- configurationController,
- keyguardUpdateMonitor,
- keyguardStateController,
- wakefulnessLifecycle,
- commandRegistry,
- notificationShadeWindowController,
- bypassController,
- biometricUnlockController,
- udfpsControllerProvider,
- statusBarStateController,
- featureFlags,
- rippleView
- )
+ controller =
+ AuthRippleController(
+ mCentralSurfaces,
+ context,
+ authController,
+ configurationController,
+ keyguardUpdateMonitor,
+ keyguardStateController,
+ wakefulnessLifecycle,
+ commandRegistry,
+ notificationShadeWindowController,
+ biometricUnlockController,
+ udfpsControllerProvider,
+ statusBarStateController,
+ featureFlags,
+ KeyguardLogger(logcatLogBuffer(AuthRippleController.TAG)),
+ rippleView
+ )
controller.init()
`when`(mCentralSurfaces.lightRevealScrim).thenReturn(lightRevealScrim)
}
@@ -127,16 +134,14 @@ class AuthRippleControllerTest : SysuiTestCase() {
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardStateController.isShowing).thenReturn(true)
- `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
- eq(BiometricSourceType.FINGERPRINT))).thenReturn(true)
+ `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(eq(FINGERPRINT)))
+ .thenReturn(true)
+ `when`(biometricUnlockController.isBiometricUnlock).thenReturn(true)
+ `when`(biometricUnlockController.biometricType).thenReturn(FINGERPRINT)
- // WHEN fingerprint authenticated
- val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
- verify(keyguardUpdateMonitor).registerCallback(captor.capture())
- captor.value.onBiometricAuthenticated(
- 0 /* userId */,
- BiometricSourceType.FINGERPRINT /* type */,
- false /* isStrongBiometric */)
+ // WHEN unlocked with fingerprint
+ verify(biometricUnlockController).addBiometricModeListener(biometricModeListener.capture())
+ biometricModeListener.value.onModeChanged(/* mode= */ 0)
// THEN update sensor location and show ripple
verify(rippleView).setFingerprintSensorLocation(fpsLocation, 0f)
@@ -149,17 +154,15 @@ class AuthRippleControllerTest : SysuiTestCase() {
val fpsLocation = Point(5, 5)
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
controller.onViewAttached()
- `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
- eq(BiometricSourceType.FINGERPRINT))).thenReturn(true)
+ `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(eq(FINGERPRINT)))
+ .thenReturn(true)
+ `when`(biometricUnlockController.isBiometricUnlock).thenReturn(true)
+ `when`(biometricUnlockController.biometricType).thenReturn(FINGERPRINT)
// WHEN keyguard is NOT showing & fingerprint authenticated
`when`(keyguardStateController.isShowing).thenReturn(false)
- val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
- verify(keyguardUpdateMonitor).registerCallback(captor.capture())
- captor.value.onBiometricAuthenticated(
- 0 /* userId */,
- BiometricSourceType.FINGERPRINT /* type */,
- false /* isStrongBiometric */)
+ verify(biometricUnlockController).addBiometricModeListener(biometricModeListener.capture())
+ biometricModeListener.value.onModeChanged(/* mode= */ 0)
// THEN no ripple
verify(rippleView, never()).startUnlockedRipple(any())
@@ -172,61 +175,14 @@ class AuthRippleControllerTest : SysuiTestCase() {
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardStateController.isShowing).thenReturn(true)
+ `when`(biometricUnlockController.isBiometricUnlock).thenReturn(true)
+ `when`(biometricUnlockController.biometricType).thenReturn(FINGERPRINT)
// WHEN unlocking with fingerprint is NOT allowed & fingerprint authenticated
- `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
- eq(BiometricSourceType.FINGERPRINT))).thenReturn(false)
- val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
- verify(keyguardUpdateMonitor).registerCallback(captor.capture())
- captor.value.onBiometricAuthenticated(
- 0 /* userId */,
- BiometricSourceType.FINGERPRINT /* type */,
- false /* isStrongBiometric */)
-
- // THEN no ripple
- verify(rippleView, never()).startUnlockedRipple(any())
- }
-
- @Test
- fun testFaceTriggerBypassEnabled_Ripple() {
- // GIVEN face auth sensor exists, keyguard is showing & unlocking with face is allowed
- val faceLocation = Point(5, 5)
- `when`(authController.faceSensorLocation).thenReturn(faceLocation)
- controller.onViewAttached()
-
- `when`(keyguardStateController.isShowing).thenReturn(true)
- `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
- BiometricSourceType.FACE)).thenReturn(true)
-
- // WHEN bypass is enabled & face authenticated
- `when`(bypassController.canBypass()).thenReturn(true)
- val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
- verify(keyguardUpdateMonitor).registerCallback(captor.capture())
- captor.value.onBiometricAuthenticated(
- 0 /* userId */,
- BiometricSourceType.FACE /* type */,
- false /* isStrongBiometric */)
-
- // THEN show ripple
- verify(rippleView).setSensorLocation(faceLocation)
- verify(rippleView).startUnlockedRipple(any())
- }
-
- @Test
- fun testFaceTriggerNonBypass_NoRipple() {
- // GIVEN face auth sensor exists
- val faceLocation = Point(5, 5)
- `when`(authController.faceSensorLocation).thenReturn(faceLocation)
- controller.onViewAttached()
-
- // WHEN bypass isn't enabled & face authenticated
- `when`(bypassController.canBypass()).thenReturn(false)
- val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
- verify(keyguardUpdateMonitor).registerCallback(captor.capture())
- captor.value.onBiometricAuthenticated(
- 0 /* userId */,
- BiometricSourceType.FACE /* type */,
- false /* isStrongBiometric */)
+ `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(eq(FINGERPRINT)))
+ .thenReturn(false)
+ verify(biometricUnlockController).addBiometricModeListener(biometricModeListener.capture())
+ biometricModeListener.value.onModeChanged(/* mode= */ 0)
// THEN no ripple
verify(rippleView, never()).startUnlockedRipple(any())
@@ -236,14 +192,12 @@ class AuthRippleControllerTest : SysuiTestCase() {
fun testNullFaceSensorLocationDoesNothing() {
`when`(authController.faceSensorLocation).thenReturn(null)
controller.onViewAttached()
+ `when`(biometricUnlockController.biometricType).thenReturn(FACE)
+ `when`(biometricUnlockController.isBiometricUnlock).thenReturn(true)
- val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
- verify(keyguardUpdateMonitor).registerCallback(captor.capture())
+ verify(biometricUnlockController).addBiometricModeListener(biometricModeListener.capture())
+ biometricModeListener.value.onModeChanged(/* mode= */ 0)
- captor.value.onBiometricAuthenticated(
- 0 /* userId */,
- BiometricSourceType.FACE /* type */,
- false /* isStrongBiometric */)
verify(rippleView, never()).startUnlockedRipple(any())
}
@@ -251,25 +205,21 @@ class AuthRippleControllerTest : SysuiTestCase() {
fun testNullFingerprintSensorLocationDoesNothing() {
`when`(authController.fingerprintSensorLocation).thenReturn(null)
controller.onViewAttached()
+ `when`(biometricUnlockController.biometricType).thenReturn(FINGERPRINT)
+ `when`(biometricUnlockController.isBiometricUnlock).thenReturn(true)
- val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
- verify(keyguardUpdateMonitor).registerCallback(captor.capture())
+ verify(biometricUnlockController).addBiometricModeListener(biometricModeListener.capture())
+ biometricModeListener.value.onModeChanged(/* mode= */ 0)
- captor.value.onBiometricAuthenticated(
- 0 /* userId */,
- BiometricSourceType.FINGERPRINT /* type */,
- false /* isStrongBiometric */)
verify(rippleView, never()).startUnlockedRipple(any())
}
@Test
fun registersAndDeregisters() {
controller.onViewAttached()
- val captor = ArgumentCaptor
- .forClass(KeyguardStateController.Callback::class.java)
+ val captor = ArgumentCaptor.forClass(KeyguardStateController.Callback::class.java)
verify(keyguardStateController).addCallback(captor.capture())
- val captor2 = ArgumentCaptor
- .forClass(WakefulnessLifecycle.Observer::class.java)
+ val captor2 = ArgumentCaptor.forClass(WakefulnessLifecycle.Observer::class.java)
verify(wakefulnessLifecycle).addObserver(captor2.capture())
controller.onViewDetached()
verify(keyguardStateController).removeCallback(any())
@@ -283,17 +233,20 @@ class AuthRippleControllerTest : SysuiTestCase() {
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardStateController.isShowing).thenReturn(true)
- `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
- BiometricSourceType.FINGERPRINT)).thenReturn(true)
+ `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(FINGERPRINT)).thenReturn(true)
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
- controller.showUnlockRipple(BiometricSourceType.FINGERPRINT)
- assertTrue("reveal didn't start on keyguardFadingAway",
- controller.startLightRevealScrimOnKeyguardFadingAway)
+ controller.showUnlockRipple(FINGERPRINT)
+ assertTrue(
+ "reveal didn't start on keyguardFadingAway",
+ controller.startLightRevealScrimOnKeyguardFadingAway
+ )
`when`(keyguardStateController.isKeyguardFadingAway).thenReturn(true)
controller.onKeyguardFadingAwayChanged()
- assertFalse("reveal triggers multiple times",
- controller.startLightRevealScrimOnKeyguardFadingAway)
+ assertFalse(
+ "reveal triggers multiple times",
+ controller.startLightRevealScrimOnKeyguardFadingAway
+ )
}
@Test
@@ -305,23 +258,26 @@ class AuthRippleControllerTest : SysuiTestCase() {
`when`(keyguardStateController.isShowing).thenReturn(true)
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
`when`(authController.isUdfpsFingerDown).thenReturn(true)
- `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
- eq(BiometricSourceType.FACE))).thenReturn(true)
+ `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(eq(FACE))).thenReturn(true)
- controller.showUnlockRipple(BiometricSourceType.FACE)
- assertTrue("reveal didn't start on keyguardFadingAway",
- controller.startLightRevealScrimOnKeyguardFadingAway)
+ controller.showUnlockRipple(FACE)
+ assertTrue(
+ "reveal didn't start on keyguardFadingAway",
+ controller.startLightRevealScrimOnKeyguardFadingAway
+ )
`when`(keyguardStateController.isKeyguardFadingAway).thenReturn(true)
controller.onKeyguardFadingAwayChanged()
- assertFalse("reveal triggers multiple times",
- controller.startLightRevealScrimOnKeyguardFadingAway)
+ assertFalse(
+ "reveal triggers multiple times",
+ controller.startLightRevealScrimOnKeyguardFadingAway
+ )
}
@Test
fun testUpdateRippleColor() {
controller.onViewAttached()
- val captor = ArgumentCaptor
- .forClass(ConfigurationController.ConfigurationListener::class.java)
+ val captor =
+ ArgumentCaptor.forClass(ConfigurationController.ConfigurationListener::class.java)
verify(configurationController).addCallback(captor.capture())
reset(rippleView)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
index 612e55732bc1..3ec49b263c54 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -63,6 +63,7 @@ import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintA
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.recents.OverviewProxyService
+import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -97,6 +98,7 @@ class SideFpsControllerTest : SysuiTestCase() {
@JvmField @Rule var rule = MockitoJUnit.rule()
+ @Mock lateinit var keyguardStateController: KeyguardStateController
@Mock lateinit var layoutInflater: LayoutInflater
@Mock lateinit var fingerprintManager: FingerprintManager
@Mock lateinit var windowManager: WindowManager
@@ -136,6 +138,7 @@ class SideFpsControllerTest : SysuiTestCase() {
keyguardBouncerRepository = FakeKeyguardBouncerRepository()
alternateBouncerInteractor =
AlternateBouncerInteractor(
+ keyguardStateController,
keyguardBouncerRepository,
FakeBiometricSettingsRepository(),
FakeDeviceEntryFingerprintAuthRepository(),
@@ -169,6 +172,7 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation: Boolean = false,
initInfo: DisplayInfo.() -> Unit = {},
windowInsets: WindowInsets = insetsForSmallNavbar(),
+ inRearDisplayMode: Boolean = false,
block: () -> Unit
) {
this.deviceConfig = deviceConfig
@@ -229,6 +233,12 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation
)
+ val rearDisplayDeviceStates = if (inRearDisplayMode) intArrayOf(3) else intArrayOf()
+ sideFpsControllerContext.orCreateTestableResources.addOverride(
+ com.android.internal.R.array.config_rearDisplayDeviceStates,
+ rearDisplayDeviceStates
+ )
+
sideFpsController =
SideFpsController(
sideFpsControllerContext,
@@ -344,7 +354,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_90() =
@@ -352,7 +364,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_90 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_180() =
@@ -360,7 +374,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_180 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_180() =
@@ -369,7 +385,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_180() =
@@ -378,7 +396,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_270() =
@@ -386,7 +406,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_0() =
@@ -394,7 +416,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -402,7 +426,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_90 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -411,7 +437,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_90 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -420,7 +448,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_90 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_180() =
@@ -428,7 +458,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_270() =
@@ -436,7 +468,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_0() =
@@ -444,7 +478,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_90() =
@@ -452,7 +488,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_90 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_180() =
@@ -470,7 +508,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_270() =
@@ -479,7 +519,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_270() =
@@ -488,7 +530,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_0() =
@@ -496,7 +540,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_90() =
@@ -514,7 +560,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_InReverseDefaultRotation_180() =
@@ -523,7 +571,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_InReverseDefaultRotation_180() =
@@ -532,7 +582,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_270() =
@@ -540,12 +592,66 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
+
+ @Test
+ fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_0() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_0 },
+ inRearDisplayMode = true,
+ ) {
+ verifySfpsIndicator_notAdded_InRearDisplayMode()
+ }
+
+ @Test
+ fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_90() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_90 },
+ inRearDisplayMode = true,
+ ) {
+ verifySfpsIndicator_notAdded_InRearDisplayMode()
+ }
+
+ @Test
+ fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_180() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_180 },
+ inRearDisplayMode = true,
+ ) {
+ verifySfpsIndicator_notAdded_InRearDisplayMode()
+ }
+
+ @Test
+ fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_270() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_270 },
+ inRearDisplayMode = true,
+ ) {
+ verifySfpsIndicator_notAdded_InRearDisplayMode()
+ }
private fun verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible: Boolean) {
sideFpsController.overlayOffsets = sensorLocation
}
+ private fun verifySfpsIndicator_notAdded_InRearDisplayMode() {
+ sideFpsController.overlayOffsets = sensorLocation
+ overlayController.show(SENSOR_ID, REASON_UNKNOWN)
+ executor.runAllReady()
+
+ verify(windowManager, never()).addView(any(), any())
+ }
+
fun alternateBouncerVisibility_showAndHideSideFpsUI() = testWithDisplay {
// WHEN alternate bouncer is visible
keyguardBouncerRepository.setAlternateVisible(true)
@@ -582,7 +688,7 @@ class SideFpsControllerTest : SysuiTestCase() {
* in other rotations have been omitted.
*/
@Test
- fun verifiesIndicatorPlacementForXAlignedSensor_0() {
+ fun verifiesIndicatorPlacementForXAlignedSensor_0() =
testWithDisplay(
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
@@ -599,7 +705,6 @@ class SideFpsControllerTest : SysuiTestCase() {
assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
}
- }
/**
* {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_270
@@ -608,7 +713,7 @@ class SideFpsControllerTest : SysuiTestCase() {
* correctly, tests for indicator placement in other rotations have been omitted.
*/
@Test
- fun verifiesIndicatorPlacementForXAlignedSensor_InReverseDefaultRotation_270() {
+ fun verifiesIndicatorPlacementForXAlignedSensor_InReverseDefaultRotation_270() =
testWithDisplay(
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
@@ -625,7 +730,6 @@ class SideFpsControllerTest : SysuiTestCase() {
assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
}
- }
/**
* {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_0,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
index c73ff1dab3d8..786cb01621bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
@@ -37,6 +37,7 @@ import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.SystemClock
import kotlinx.coroutines.Dispatchers
@@ -86,11 +87,13 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle
mock(PrimaryBouncerCallbackInteractor::class.java),
mock(FalsingCollector::class.java),
mock(DismissCallbackRegistry::class.java),
+ context,
+ mKeyguardUpdateMonitor,
mock(KeyguardBypassController::class.java),
- mKeyguardUpdateMonitor
)
mAlternateBouncerInteractor =
AlternateBouncerInteractor(
+ mock(KeyguardStateController::class.java),
keyguardBouncerRepository,
mock(BiometricSettingsRepository::class.java),
mock(DeviceEntryFingerprintAuthRepository::class.java),
@@ -135,7 +138,7 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle
// WHEN the bouncer expansion is VISIBLE
val job = mController.listenForBouncerExpansion(this)
- keyguardBouncerRepository.setPrimaryVisible(true)
+ keyguardBouncerRepository.setPrimaryShow(true)
keyguardBouncerRepository.setPanelExpansion(KeyguardBouncerConstants.EXPANSION_VISIBLE)
yield()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java
index a61cecbabf30..9d16185e75c5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java
@@ -20,14 +20,14 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
-import androidx.test.filters.SmallTest;
-
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -44,18 +44,22 @@ import org.mockito.MockitoAnnotations;
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class BroadcastDialogTest extends SysuiTestCase {
- private static final String SWITCH_APP = "Music";
- private static final String TEST_PACKAGE = "com.google.android.apps.nbu.files";
+ private static final String CURRENT_BROADCAST_APP = "Music";
+ private static final String SWITCH_APP = "System UI";
+ private static final String TEST_PACKAGE = "com.android.systemui";
private BroadcastDialog mBroadcastDialog;
private View mDialogView;
+ private TextView mTitle;
private TextView mSubTitle;
+ private Button mSwitchBroadcastAppButton;
private Button mChangeOutputButton;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mBroadcastDialog = new BroadcastDialog(mContext, mock(MediaOutputDialogFactory.class),
- SWITCH_APP, TEST_PACKAGE, mock(UiEventLogger.class));
+ CURRENT_BROADCAST_APP, TEST_PACKAGE, mock(UiEventLogger.class));
+
mBroadcastDialog.show();
mDialogView = mBroadcastDialog.mDialogView;
}
@@ -66,7 +70,15 @@ public class BroadcastDialogTest extends SysuiTestCase {
}
@Test
- public void onCreate_withCurrentApp_checkSwitchAppContent() {
+ public void onCreate_withCurrentApp_titleIsCurrentAppName() {
+ mTitle = mDialogView.requireViewById(R.id.dialog_title);
+
+ assertThat(mTitle.getText().toString()).isEqualTo(mContext.getString(
+ R.string.bt_le_audio_broadcast_dialog_title, CURRENT_BROADCAST_APP));
+ }
+
+ @Test
+ public void onCreate_withCurrentApp_subTitleIsSwitchAppName() {
mSubTitle = mDialogView.requireViewById(R.id.dialog_subtitle);
assertThat(mSubTitle.getText()).isEqualTo(
@@ -74,6 +86,14 @@ public class BroadcastDialogTest extends SysuiTestCase {
}
@Test
+ public void onCreate_withCurrentApp_switchBtnIsSwitchAppName() {
+ mSwitchBroadcastAppButton = mDialogView.requireViewById(R.id.switch_broadcast);
+
+ assertThat(mSwitchBroadcastAppButton.getText().toString()).isEqualTo(
+ mContext.getString(R.string.bt_le_audio_broadcast_dialog_switch_app, SWITCH_APP));
+ }
+
+ @Test
public void onClick_withChangeOutput_dismissBroadcastDialog() {
mChangeOutputButton = mDialogView.requireViewById(R.id.change_output);
mChangeOutputButton.performClick();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
index e4df754ec96a..8cb91304808d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
@@ -106,7 +106,7 @@ public class BrightLineClassifierTest extends SysuiTestCase {
mClassifiers.add(mClassifierB);
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
when(mKeyguardStateController.isShowing()).thenReturn(true);
- when(mFalsingDataProvider.isFolded()).thenReturn(true);
+ when(mFalsingDataProvider.isUnfolded()).thenReturn(false);
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
mMetricsLogger, mClassifiers, mSingleTapClassfier, mLongTapClassifier,
mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
index ae38eb67c431..315774aad71a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
@@ -89,7 +89,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
mClassifiers.add(mClassifierA);
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
when(mKeyguardStateController.isShowing()).thenReturn(true);
- when(mFalsingDataProvider.isFolded()).thenReturn(true);
+ when(mFalsingDataProvider.isUnfolded()).thenReturn(false);
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
mMetricsLogger, mClassifiers, mSingleTapClassifier, mLongTapClassifier,
mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
@@ -185,7 +185,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
@Test
public void testSkipUnfolded() {
assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue();
- when(mFalsingDataProvider.isFolded()).thenReturn(false);
+ when(mFalsingDataProvider.isUnfolded()).thenReturn(true);
assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
index faa5db4327a6..ab6d5b771d5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
@@ -94,7 +94,9 @@ public class DistanceClassifierTest extends ClassifierTest {
mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3));
mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300));
mClassifier.onTouchEvent(appendMoveEvent(1, 18, 301));
- mClassifier.onTouchEvent(appendUpEvent(1, 19, 501));
+ mClassifier.onTouchEvent(appendMoveEvent(1, 19, 501));
+ mClassifier.onTouchEvent(appendUpEvent(1, 19, 501)); //event will be dropped
+
assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
index c451a1e754c9..8eadadff1ca5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
@@ -75,16 +75,17 @@ public class FalsingDataProviderTest extends ClassifierTest {
}
@Test
- public void test_trackMotionEvents() {
+ public void test_trackMotionEvents_dropUpEvent() {
mDataProvider.onMotionEvent(appendDownEvent(2, 9));
mDataProvider.onMotionEvent(appendMoveEvent(4, 7));
- mDataProvider.onMotionEvent(appendUpEvent(6, 5));
+ mDataProvider.onMotionEvent(appendMoveEvent(6, 5));
+ mDataProvider.onMotionEvent(appendUpEvent(0, 0)); // event will be dropped
List<MotionEvent> motionEventList = mDataProvider.getRecentMotionEvents();
assertThat(motionEventList.size()).isEqualTo(3);
assertThat(motionEventList.get(0).getActionMasked()).isEqualTo(MotionEvent.ACTION_DOWN);
assertThat(motionEventList.get(1).getActionMasked()).isEqualTo(MotionEvent.ACTION_MOVE);
- assertThat(motionEventList.get(2).getActionMasked()).isEqualTo(MotionEvent.ACTION_UP);
+ assertThat(motionEventList.get(2).getActionMasked()).isEqualTo(MotionEvent.ACTION_MOVE);
assertThat(motionEventList.get(0).getEventTime()).isEqualTo(1L);
assertThat(motionEventList.get(1).getEventTime()).isEqualTo(2L);
assertThat(motionEventList.get(2).getEventTime()).isEqualTo(3L);
@@ -97,6 +98,28 @@ public class FalsingDataProviderTest extends ClassifierTest {
}
@Test
+ public void test_trackMotionEvents_keepUpEvent() {
+ mDataProvider.onMotionEvent(appendDownEvent(2, 9));
+ mDataProvider.onMotionEvent(appendMoveEvent(4, 7));
+ mDataProvider.onMotionEvent(appendUpEvent(0, 0, 100));
+ List<MotionEvent> motionEventList = mDataProvider.getRecentMotionEvents();
+
+ assertThat(motionEventList.size()).isEqualTo(3);
+ assertThat(motionEventList.get(0).getActionMasked()).isEqualTo(MotionEvent.ACTION_DOWN);
+ assertThat(motionEventList.get(1).getActionMasked()).isEqualTo(MotionEvent.ACTION_MOVE);
+ assertThat(motionEventList.get(2).getActionMasked()).isEqualTo(MotionEvent.ACTION_UP);
+ assertThat(motionEventList.get(0).getEventTime()).isEqualTo(1L);
+ assertThat(motionEventList.get(1).getEventTime()).isEqualTo(2L);
+ assertThat(motionEventList.get(2).getEventTime()).isEqualTo(100);
+ assertThat(motionEventList.get(0).getX()).isEqualTo(2f);
+ assertThat(motionEventList.get(1).getX()).isEqualTo(4f);
+ assertThat(motionEventList.get(2).getX()).isEqualTo(0f);
+ assertThat(motionEventList.get(0).getY()).isEqualTo(9f);
+ assertThat(motionEventList.get(1).getY()).isEqualTo(7f);
+ assertThat(motionEventList.get(2).getY()).isEqualTo(0f);
+ }
+
+ @Test
public void test_trackRecentMotionEvents() {
mDataProvider.onMotionEvent(appendDownEvent(2, 9, 1));
mDataProvider.onMotionEvent(appendMoveEvent(4, 7, 800));
@@ -324,12 +347,18 @@ public class FalsingDataProviderTest extends ClassifierTest {
@Test
public void test_FoldedState_Folded() {
when(mFoldStateListener.getFolded()).thenReturn(true);
- assertThat(mDataProvider.isFolded()).isTrue();
+ assertThat(mDataProvider.isUnfolded()).isFalse();
}
@Test
public void test_FoldedState_Unfolded() {
when(mFoldStateListener.getFolded()).thenReturn(false);
- assertThat(mDataProvider.isFolded()).isFalse();
+ assertThat(mDataProvider.isUnfolded()).isTrue();
+ }
+
+ @Test
+ public void test_FoldedState_NotFoldable() {
+ when(mFoldStateListener.getFolded()).thenReturn(null);
+ assertThat(mDataProvider.isUnfolded()).isFalse();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
index c343c20398e9..ae2b8bbb4ce6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
@@ -68,6 +68,15 @@ public class ZigZagClassifierTest extends ClassifierTest {
}
@Test
+ public void testPass_dropClosingUpEvent() {
+ appendMoveEvent(0, 0);
+ appendMoveEvent(0, 100);
+ appendMoveEvent(0, 200);
+ appendUpEvent(0, 180); // this event would push us over the maxDevianceY
+ assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
+ }
+
+ @Test
public void testPass_fewTouchesHorizontal() {
assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
appendMoveEvent(0, 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
index 2099281d694a..ffd75fb9bbc6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
@@ -35,6 +35,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.app.RemoteAction;
import android.content.ClipData;
import android.content.ClipDescription;
@@ -101,6 +102,9 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
private ArgumentCaptor<ClipboardOverlayView.ClipboardOverlayCallbacks> mOverlayCallbacksCaptor;
private ClipboardOverlayView.ClipboardOverlayCallbacks mCallbacks;
+ @Captor
+ private ArgumentCaptor<AnimatorListenerAdapter> mAnimatorArgumentCaptor;
+
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@Before
@@ -446,7 +450,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true);
when(mClipboardUtils.isRemoteCopy(any(Context.class), any(ClipData.class), anyString()))
.thenReturn(true);
- when(mClipboardUtils.getAction(any(CharSequence.class), any(TextLinks.class), anyString()))
+ when(mClipboardUtils.getAction(any(TextLinks.class), anyString()))
.thenReturn(Optional.of(Mockito.mock(RemoteAction.class)));
when(mClipboardOverlayView.post(any(Runnable.class))).thenAnswer(new Answer<Object>() {
@Override
@@ -478,12 +482,16 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
when(mClipboardOverlayWindow.getWindowInsets()).thenReturn(
getImeInsets(new Rect(0, 0, 0, 1)));
mOverlayController.setClipData(mSampleClipData, "");
+ Animator mockFadeoutAnimator = Mockito.mock(Animator.class);
+ when(mClipboardOverlayView.getMinimizedFadeoutAnimation()).thenReturn(mockFadeoutAnimator);
verify(mClipboardOverlayView).setMinimized(true);
verify(mClipboardOverlayView, never()).setMinimized(false);
verify(mClipboardOverlayView, never()).showTextPreview(any(), anyBoolean());
mCallbacks.onMinimizedViewTapped();
+ verify(mockFadeoutAnimator).addListener(mAnimatorArgumentCaptor.capture());
+ mAnimatorArgumentCaptor.getValue().onAnimationEnd(mockFadeoutAnimator);
verify(mClipboardOverlayView).setMinimized(false);
verify(mClipboardOverlayView).showTextPreview("Test Item", false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java
index aea6be3d468b..3d8f04e08825 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java
@@ -21,6 +21,7 @@ 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.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.when;
@@ -77,6 +78,74 @@ public class ClipboardOverlayUtilsTest extends SysuiTestCase {
@Test
public void test_getAction_noLinks_returnsEmptyOptional() {
+ Optional<RemoteAction> action =
+ mClipboardUtils.getAction(Mockito.mock(TextLinks.class), "abc");
+
+ assertTrue(action.isEmpty());
+ }
+
+ @Test
+ public void test_getAction_returnsFirstLink() {
+ TextLinks links = getFakeTextLinksBuilder().build();
+ RemoteAction actionA = constructRemoteAction("abc");
+ RemoteAction actionB = constructRemoteAction("def");
+ TextClassification classificationA = Mockito.mock(TextClassification.class);
+ when(classificationA.getActions()).thenReturn(Lists.newArrayList(actionA));
+ TextClassification classificationB = Mockito.mock(TextClassification.class);
+ when(classificationB.getActions()).thenReturn(Lists.newArrayList(actionB));
+ when(mTextClassifier.classifyText(anyString(), anyInt(), anyInt(), isNull())).thenReturn(
+ classificationA, classificationB);
+
+ RemoteAction result = mClipboardUtils.getAction(links, "test").orElse(null);
+
+ assertEquals(actionA, result);
+ }
+
+ @Test
+ public void test_getAction_skipsMatchingComponent() {
+ TextLinks links = getFakeTextLinksBuilder().build();
+ RemoteAction actionA = constructRemoteAction("abc");
+ RemoteAction actionB = constructRemoteAction("def");
+ TextClassification classificationA = Mockito.mock(TextClassification.class);
+ when(classificationA.getActions()).thenReturn(Lists.newArrayList(actionA));
+ TextClassification classificationB = Mockito.mock(TextClassification.class);
+ when(classificationB.getActions()).thenReturn(Lists.newArrayList(actionB));
+ when(mTextClassifier.classifyText(anyString(), anyInt(), anyInt(), isNull())).thenReturn(
+ classificationA, classificationB);
+
+ RemoteAction result = mClipboardUtils.getAction(links, "abc").orElse(null);
+
+ assertEquals(actionB, result);
+ }
+
+ @Test
+ public void test_getAction_skipsShortEntity() {
+ TextLinks.Builder textLinks = new TextLinks.Builder("test text of length 22");
+ final Map<String, Float> scores = new ArrayMap<>();
+ scores.put(TextClassifier.TYPE_EMAIL, 1f);
+ textLinks.addLink(20, 22, scores);
+ textLinks.addLink(0, 22, scores);
+
+ RemoteAction actionA = constructRemoteAction("abc");
+ RemoteAction actionB = constructRemoteAction("def");
+ TextClassification classificationA = Mockito.mock(TextClassification.class);
+ when(classificationA.getActions()).thenReturn(Lists.newArrayList(actionA));
+ TextClassification classificationB = Mockito.mock(TextClassification.class);
+ when(classificationB.getActions()).thenReturn(Lists.newArrayList(actionB));
+ when(mTextClassifier.classifyText(anyString(), eq(20), eq(22), isNull())).thenReturn(
+ classificationA);
+ when(mTextClassifier.classifyText(anyString(), eq(0), eq(22), isNull())).thenReturn(
+ classificationB);
+
+ RemoteAction result = mClipboardUtils.getAction(textLinks.build(), "test").orElse(null);
+
+ assertEquals(actionB, result);
+ }
+
+ // TODO(b/267162944): Next four tests (marked "legacy") are obsolete once
+ // CLIPBOARD_MINIMIZED_LAYOUT flag is released and removed
+ @Test
+ public void test_getAction_noLinks_returnsEmptyOptional_legacy() {
ClipData.Item item = new ClipData.Item("no text links");
item.setTextLinks(Mockito.mock(TextLinks.class));
@@ -86,8 +155,8 @@ public class ClipboardOverlayUtilsTest extends SysuiTestCase {
}
@Test
- public void test_getAction_returnsFirstLink() {
- when(mClipDataItem.getTextLinks()).thenReturn(getFakeTextLinks());
+ public void test_getAction_returnsFirstLink_legacy() {
+ when(mClipDataItem.getTextLinks()).thenReturn(getFakeTextLinksBuilder().build());
when(mClipDataItem.getText()).thenReturn("");
RemoteAction actionA = constructRemoteAction("abc");
RemoteAction actionB = constructRemoteAction("def");
@@ -98,14 +167,14 @@ public class ClipboardOverlayUtilsTest extends SysuiTestCase {
when(mTextClassifier.classifyText(anyString(), anyInt(), anyInt(), isNull())).thenReturn(
classificationA, classificationB);
- RemoteAction result = mClipboardUtils.getAction(mClipDataItem, "def").orElse(null);
+ RemoteAction result = mClipboardUtils.getAction(mClipDataItem, "test").orElse(null);
assertEquals(actionA, result);
}
@Test
- public void test_getAction_skipsMatchingComponent() {
- when(mClipDataItem.getTextLinks()).thenReturn(getFakeTextLinks());
+ public void test_getAction_skipsMatchingComponent_legacy() {
+ when(mClipDataItem.getTextLinks()).thenReturn(getFakeTextLinksBuilder().build());
when(mClipDataItem.getText()).thenReturn("");
RemoteAction actionA = constructRemoteAction("abc");
RemoteAction actionB = constructRemoteAction("def");
@@ -122,6 +191,33 @@ public class ClipboardOverlayUtilsTest extends SysuiTestCase {
}
@Test
+ public void test_getAction_skipsShortEntity_legacy() {
+ TextLinks.Builder textLinks = new TextLinks.Builder("test text of length 22");
+ final Map<String, Float> scores = new ArrayMap<>();
+ scores.put(TextClassifier.TYPE_EMAIL, 1f);
+ textLinks.addLink(20, 22, scores);
+ textLinks.addLink(0, 22, scores);
+
+ when(mClipDataItem.getTextLinks()).thenReturn(textLinks.build());
+ when(mClipDataItem.getText()).thenReturn(textLinks.build().getText());
+
+ RemoteAction actionA = constructRemoteAction("abc");
+ RemoteAction actionB = constructRemoteAction("def");
+ TextClassification classificationA = Mockito.mock(TextClassification.class);
+ when(classificationA.getActions()).thenReturn(Lists.newArrayList(actionA));
+ TextClassification classificationB = Mockito.mock(TextClassification.class);
+ when(classificationB.getActions()).thenReturn(Lists.newArrayList(actionB));
+ when(mTextClassifier.classifyText(anyString(), eq(20), eq(22), isNull())).thenReturn(
+ classificationA);
+ when(mTextClassifier.classifyText(anyString(), eq(0), eq(22), isNull())).thenReturn(
+ classificationB);
+
+ RemoteAction result = mClipboardUtils.getAction(mClipDataItem, "test").orElse(null);
+
+ assertEquals(actionB, result);
+ }
+
+ @Test
public void test_extra_withPackage_returnsTrue() {
PersistableBundle b = new PersistableBundle();
b.putBoolean(ClipDescription.EXTRA_IS_REMOTE_DEVICE, true);
@@ -184,12 +280,12 @@ public class ClipboardOverlayUtilsTest extends SysuiTestCase {
return action;
}
- private static TextLinks getFakeTextLinks() {
- TextLinks.Builder textLinks = new TextLinks.Builder("test");
+ private static TextLinks.Builder getFakeTextLinksBuilder() {
+ TextLinks.Builder textLinks = new TextLinks.Builder("test text of length 22");
final Map<String, Float> scores = new ArrayMap<>();
scores.put(TextClassifier.TYPE_EMAIL, 1f);
- textLinks.addLink(0, 0, scores);
- textLinks.addLink(0, 0, scores);
- return textLinks.build();
+ textLinks.addLink(0, 22, scores);
+ textLinks.addLink(0, 22, scores);
+ return textLinks;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
index 2ed03465c6f0..eafe727ee7dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SeekBar;
@@ -42,6 +43,8 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
private ImageView mIconStart;
private ImageView mIconEnd;
+ private ViewGroup mIconStartFrame;
+ private ViewGroup mIconEndFrame;
private SeekBar mSeekbar;
private SeekBarWithIconButtonsView mIconDiscreteSliderLinearLayout;
@@ -50,6 +53,8 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
mIconDiscreteSliderLinearLayout = new SeekBarWithIconButtonsView(mContext);
mIconStart = mIconDiscreteSliderLinearLayout.findViewById(R.id.icon_start);
mIconEnd = mIconDiscreteSliderLinearLayout.findViewById(R.id.icon_end);
+ mIconStartFrame = mIconDiscreteSliderLinearLayout.findViewById(R.id.icon_start_frame);
+ mIconEndFrame = mIconDiscreteSliderLinearLayout.findViewById(R.id.icon_end_frame);
mSeekbar = mIconDiscreteSliderLinearLayout.findViewById(R.id.seekbar);
}
@@ -59,6 +64,8 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
assertThat(mIconStart.isEnabled()).isFalse();
assertThat(mIconEnd.isEnabled()).isTrue();
+ assertThat(mIconStartFrame.isEnabled()).isFalse();
+ assertThat(mIconEndFrame.isEnabled()).isTrue();
}
@Test
@@ -67,6 +74,8 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
assertThat(mIconEnd.isEnabled()).isFalse();
assertThat(mIconStart.isEnabled()).isTrue();
+ assertThat(mIconEndFrame.isEnabled()).isFalse();
+ assertThat(mIconStartFrame.isEnabled()).isTrue();
}
@Test
@@ -77,12 +86,15 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
assertThat(mIconStart.isEnabled()).isTrue();
assertThat(mIconEnd.isEnabled()).isTrue();
+ assertThat(mIconStartFrame.isEnabled()).isTrue();
+ assertThat(mIconEndFrame.isEnabled()).isTrue();
}
@Test
public void clickIconEnd_currentProgressIsOneToMax_reachesMax() {
mIconDiscreteSliderLinearLayout.setProgress(mSeekbar.getMax() - 1);
- mIconEnd.performClick();
+
+ mIconEndFrame.performClick();
assertThat(mSeekbar.getProgress()).isEqualTo(mSeekbar.getMax());
}
@@ -90,7 +102,8 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
@Test
public void clickIconStart_currentProgressIsOne_reachesZero() {
mIconDiscreteSliderLinearLayout.setProgress(1);
- mIconStart.performClick();
+
+ mIconStartFrame.performClick();
assertThat(mSeekbar.getProgress()).isEqualTo(0);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index e35b2a384bd0..c98d5374311d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -34,16 +34,15 @@ import com.android.systemui.controls.ControlStatus
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.FakeSelectedComponentRepository
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.dump.DumpManager
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
-import java.io.File
-import java.util.Optional
-import java.util.function.Consumer
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@@ -59,6 +58,7 @@ import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
@@ -67,8 +67,10 @@ import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when`
-import org.mockito.Mockito.clearInvocations
import org.mockito.MockitoAnnotations
+import java.io.File
+import java.util.*
+import java.util.function.Consumer
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -107,6 +109,8 @@ class ControlsControllerImplTest : SysuiTestCase() {
private lateinit var listingCallbackCaptor:
ArgumentCaptor<ControlsListingController.ControlsListingCallback>
+ private val preferredPanelRepository = FakeSelectedComponentRepository()
+
private lateinit var delayableExecutor: FakeExecutor
private lateinit var controller: ControlsControllerImpl
private lateinit var canceller: DidRunRunnable
@@ -146,6 +150,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
+ whenever(authorizedPanelsRepository.getAuthorizedPanels()).thenReturn(setOf())
`when`(userTracker.userHandle).thenReturn(UserHandle.of(user))
delayableExecutor = FakeExecutor(FakeSystemClock())
@@ -166,6 +171,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
wrapper,
delayableExecutor,
uiController,
+ preferredPanelRepository,
bindingController,
listingController,
userFileManager,
@@ -219,6 +225,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
mContext,
delayableExecutor,
uiController,
+ preferredPanelRepository,
bindingController,
listingController,
userFileManager,
@@ -238,6 +245,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
mContext,
delayableExecutor,
uiController,
+ preferredPanelRepository,
bindingController,
listingController,
userFileManager,
@@ -945,6 +953,28 @@ class ControlsControllerImplTest : SysuiTestCase() {
controller.bindComponentForPanel(TEST_COMPONENT)
verify(bindingController).bindServiceForPanel(TEST_COMPONENT)
}
+
+ @Test
+ fun testRemoveFavoriteRemovesFavorite() {
+ val componentName = ComponentName(context, "test.Cls")
+ controller.addFavorite(
+ componentName,
+ "test structure",
+ ControlInfo(
+ controlId = "testId",
+ controlTitle = "Test Control",
+ controlSubtitle = "test control subtitle",
+ deviceType = DeviceTypes.TYPE_LIGHT,
+ ),
+ )
+
+ controller.removeFavorites(componentName)
+ delayableExecutor.runAllReady()
+
+ verify(authorizedPanelsRepository)
+ .removeAuthorizedPanels(eq(setOf(componentName.packageName)))
+ assertThat(controller.getFavorites()).isEmpty()
+ }
}
private class DidRunRunnable() : Runnable {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
index 35cd3d261562..10bfc1b292d3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
@@ -45,6 +45,8 @@ import com.android.systemui.util.mockito.argThat
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Executor
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
@@ -62,7 +64,6 @@ import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-import java.util.concurrent.Executor
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -106,6 +107,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this)
`when`(userTracker.userId).thenReturn(user)
+ `when`(userTracker.userHandle).thenReturn(UserHandle.of(user))
`when`(userTracker.userContext).thenReturn(context)
// Return disabled by default
`when`(packageManager.getComponentEnabledSetting(any()))
@@ -564,6 +566,79 @@ class ControlsListingControllerImplTest : SysuiTestCase() {
assertTrue(controller.getCurrentServices().isEmpty())
}
+ @Test
+ fun testForceReloadQueriesPackageManager() {
+ val user = 10
+ `when`(userTracker.userHandle).thenReturn(UserHandle.of(user))
+
+ controller.forceReload()
+ verify(packageManager).queryIntentServicesAsUser(
+ argThat(IntentMatcherAction(ControlsProviderService.SERVICE_CONTROLS)),
+ argThat(FlagsMatcher(
+ PackageManager.GET_META_DATA.toLong() or
+ PackageManager.GET_SERVICES.toLong() or
+ PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or
+ PackageManager.MATCH_DIRECT_BOOT_UNAWARE.toLong()
+ )),
+ eq(UserHandle.of(user))
+ )
+ }
+
+ @Test
+ fun testForceReloadUpdatesList() {
+ val resolveInfo = ResolveInfo()
+ resolveInfo.serviceInfo = ServiceInfo(componentName)
+
+ `when`(packageManager.queryIntentServicesAsUser(
+ argThat(IntentMatcherAction(ControlsProviderService.SERVICE_CONTROLS)),
+ argThat(FlagsMatcher(
+ PackageManager.GET_META_DATA.toLong() or
+ PackageManager.GET_SERVICES.toLong() or
+ PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or
+ PackageManager.MATCH_DIRECT_BOOT_UNAWARE.toLong()
+ )),
+ any<UserHandle>()
+ )).thenReturn(listOf(resolveInfo))
+
+ controller.forceReload()
+
+ val services = controller.getCurrentServices()
+ assertThat(services.size).isEqualTo(1)
+ assertThat(services[0].serviceInfo.componentName).isEqualTo(componentName)
+ }
+
+ @Test
+ fun testForceReloadCallsListeners() {
+ controller.addCallback(mockCallback)
+ executor.runAllReady()
+
+ @Suppress("unchecked_cast")
+ val captor: ArgumentCaptor<List<ControlsServiceInfo>> =
+ ArgumentCaptor.forClass(List::class.java)
+ as ArgumentCaptor<List<ControlsServiceInfo>>
+
+ val resolveInfo = ResolveInfo()
+ resolveInfo.serviceInfo = ServiceInfo(componentName)
+
+ `when`(packageManager.queryIntentServicesAsUser(
+ any(),
+ any<PackageManager.ResolveInfoFlags>(),
+ any<UserHandle>()
+ )).thenReturn(listOf(resolveInfo))
+
+ reset(mockCallback)
+ controller.forceReload()
+
+ verify(mockCallback).onServicesUpdated(capture(captor))
+
+ val services = captor.value
+
+ assertThat(services.size).isEqualTo(1)
+ assertThat(services[0].serviceInfo.componentName).isEqualTo(componentName)
+ }
+
+
+
private fun ServiceInfo(
componentName: ComponentName,
panelActivityComponentName: ComponentName? = null
@@ -600,7 +675,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() {
private fun setUpQueryResult(infos: List<ActivityInfo>) {
`when`(
packageManager.queryIntentActivitiesAsUser(
- argThat(IntentMatcher(activityName)),
+ argThat(IntentMatcherComponent(activityName)),
argThat(FlagsMatcher(FLAGS)),
eq(UserHandle.of(user))
)
@@ -609,7 +684,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() {
})
}
- private class IntentMatcher(
+ private class IntentMatcherComponent(
private val componentName: ComponentName
) : ArgumentMatcher<Intent> {
override fun matches(argument: Intent?): Boolean {
@@ -617,6 +692,14 @@ class ControlsListingControllerImplTest : SysuiTestCase() {
}
}
+ private class IntentMatcherAction(
+ private val action: String
+ ) : ArgumentMatcher<Intent> {
+ override fun matches(argument: Intent?): Boolean {
+ return argument?.action == action
+ }
+ }
+
private class FlagsMatcher(
private val flags: Long
) : ArgumentMatcher<PackageManager.ResolveInfoFlags> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
index b91a3fd4b28c..272f5895390c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
@@ -22,6 +22,8 @@ import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.FakeSharedPreferences
@@ -40,6 +42,8 @@ class AuthorizedPanelsRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var userTracker: UserTracker
+ private val featureFlags = FakeFeatureFlags()
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -48,6 +52,7 @@ class AuthorizedPanelsRepositoryImplTest : SysuiTestCase() {
arrayOf<String>()
)
whenever(userTracker.userId).thenReturn(0)
+ featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, true)
}
@Test
@@ -115,8 +120,37 @@ class AuthorizedPanelsRepositoryImplTest : SysuiTestCase() {
assertThat(sharedPrefs.getStringSet(KEY, null)).containsExactly(TEST_PACKAGE)
}
+ @Test
+ fun testRemoveAuthorizedPackageRemovesIt() {
+ val sharedPrefs = FakeSharedPreferences()
+ val fileManager = FakeUserFileManager(mapOf(0 to sharedPrefs))
+ val repository = createRepository(fileManager)
+ repository.addAuthorizedPanels(setOf(TEST_PACKAGE))
+
+ repository.removeAuthorizedPanels(setOf(TEST_PACKAGE))
+
+ assertThat(sharedPrefs.getStringSet(KEY, null)).isEmpty()
+ }
+
+ @Test
+ fun testSetAuthorizedPackageAfterFeatureDisabled() {
+ mContext.orCreateTestableResources.addOverride(
+ R.array.config_controlsPreferredPackages,
+ arrayOf(TEST_PACKAGE)
+ )
+ val sharedPrefs = FakeSharedPreferences()
+ val fileManager = FakeUserFileManager(mapOf(0 to sharedPrefs))
+ val repository = createRepository(fileManager)
+
+ repository.removeAuthorizedPanels(setOf(TEST_PACKAGE))
+
+ featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, false)
+
+ assertThat(repository.getAuthorizedPanels()).isEqualTo(setOf(TEST_PACKAGE))
+ }
+
private fun createRepository(userFileManager: UserFileManager): AuthorizedPanelsRepositoryImpl {
- return AuthorizedPanelsRepositoryImpl(mContext, userFileManager, userTracker)
+ return AuthorizedPanelsRepositoryImpl(mContext, userFileManager, userTracker, featureFlags)
}
private class FakeUserFileManager(private val sharedPrefs: Map<Int, SharedPreferences>) :
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/FakeSelectedComponentRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/FakeSelectedComponentRepository.kt
new file mode 100644
index 000000000000..a7677cca9f29
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/FakeSelectedComponentRepository.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.panels
+
+class FakeSelectedComponentRepository : SelectedComponentRepository {
+
+ private var selectedComponent: SelectedComponentRepository.SelectedComponent? = null
+ private var shouldAddDefaultPanel: Boolean = true
+
+ override fun getSelectedComponent(): SelectedComponentRepository.SelectedComponent? =
+ selectedComponent
+
+ override fun setSelectedComponent(
+ selectedComponent: SelectedComponentRepository.SelectedComponent
+ ) {
+ this.selectedComponent = selectedComponent
+ }
+
+ override fun removeSelectedComponent() {
+ selectedComponent = null
+ }
+
+ override fun shouldAddDefaultComponent(): Boolean = shouldAddDefaultPanel
+
+ override fun setShouldAddDefaultComponent(shouldAdd: Boolean) {
+ shouldAddDefaultPanel = shouldAdd
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/SelectedComponentRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/SelectedComponentRepositoryTest.kt
new file mode 100644
index 000000000000..0c7b9cb82b94
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/SelectedComponentRepositoryTest.kt
@@ -0,0 +1,163 @@
+/*
+ * 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.controls.panels
+
+import android.content.ComponentName
+import android.content.SharedPreferences
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
+import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.mockito.any
+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
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class SelectedComponentRepositoryTest : SysuiTestCase() {
+
+ private companion object {
+ val COMPONENT_A =
+ SelectedComponentRepository.SelectedComponent(
+ name = "a",
+ componentName = ComponentName.unflattenFromString("pkg/.cls_a"),
+ isPanel = false,
+ )
+ val COMPONENT_B =
+ SelectedComponentRepository.SelectedComponent(
+ name = "b",
+ componentName = ComponentName.unflattenFromString("pkg/.cls_b"),
+ isPanel = false,
+ )
+ }
+
+ @Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var userFileManager: UserFileManager
+
+ private val featureFlags = FakeFeatureFlags()
+ private val sharedPreferences: SharedPreferences = FakeSharedPreferences()
+
+ // under test
+ private lateinit var repository: SelectedComponentRepository
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(userFileManager.getSharedPreferences(any(), any(), any()))
+ .thenReturn(sharedPreferences)
+
+ repository = SelectedComponentRepositoryImpl(userFileManager, userTracker, featureFlags)
+ }
+
+ @Test
+ fun testUnsetIsNull() {
+ assertThat(repository.getSelectedComponent()).isNull()
+ }
+
+ @Test
+ fun testGetReturnsSet() {
+ repository.setSelectedComponent(COMPONENT_A)
+
+ assertThat(repository.getSelectedComponent()).isEqualTo(COMPONENT_A)
+ }
+
+ @Test
+ fun testSetOverrides() {
+ repository.setSelectedComponent(COMPONENT_A)
+ repository.setSelectedComponent(COMPONENT_B)
+
+ assertThat(repository.getSelectedComponent()).isEqualTo(COMPONENT_B)
+ }
+
+ @Test
+ fun testRemove() {
+ repository.setSelectedComponent(COMPONENT_A)
+
+ repository.removeSelectedComponent()
+
+ assertThat(repository.getSelectedComponent()).isNull()
+ }
+
+ @Test
+ fun testFeatureEnabled_shouldAddDefaultPanelDefaultsToTrue() {
+ featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, true)
+
+ assertThat(repository.shouldAddDefaultComponent()).isTrue()
+ }
+
+ @Test
+ fun testFeatureDisabled_shouldAddDefaultPanelDefaultsToTrue() {
+ featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, false)
+
+ assertThat(repository.shouldAddDefaultComponent()).isTrue()
+ }
+
+ @Test
+ fun testFeatureEnabled_shouldAddDefaultPanelChecked() {
+ featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, true)
+ repository.setShouldAddDefaultComponent(false)
+
+ assertThat(repository.shouldAddDefaultComponent()).isFalse()
+ }
+
+ @Test
+ fun testFeatureDisabled_shouldAlwaysAddDefaultPanelAlwaysTrue() {
+ featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, false)
+ repository.setShouldAddDefaultComponent(false)
+
+ assertThat(repository.shouldAddDefaultComponent()).isTrue()
+ }
+
+ @Test
+ fun testGetPreferredStructure_differentUserId() {
+ sharedPreferences.savePanel(COMPONENT_A)
+ whenever(
+ userFileManager.getSharedPreferences(
+ DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
+ 0,
+ 1,
+ )
+ )
+ .thenReturn(FakeSharedPreferences().also { it.savePanel(COMPONENT_B) })
+
+ val previousPreferredStructure = repository.getSelectedComponent()
+ whenever(userTracker.userId).thenReturn(1)
+ val currentPreferredStructure = repository.getSelectedComponent()
+
+ assertThat(previousPreferredStructure).isEqualTo(COMPONENT_A)
+ assertThat(currentPreferredStructure).isNotEqualTo(previousPreferredStructure)
+ assertThat(currentPreferredStructure).isEqualTo(COMPONENT_B)
+ }
+
+ private fun SharedPreferences.savePanel(panel: SelectedComponentRepository.SelectedComponent) {
+ edit()
+ .putString("controls_component", panel.componentName?.flattenToString())
+ .putString("controls_structure", panel.name)
+ .putBoolean("controls_is_panel", panel.isPanel)
+ .commit()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
index 0c9986d82447..5a613aa9225e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
@@ -104,7 +104,9 @@ class ControlsSettingsDialogManagerImplTest : SysuiTestCase() {
controlsSettingsRepository,
userTracker,
activityStarter
- ) { context, _ -> TestableAlertDialog(context).also { dialog = it } }
+ ) { context, _ ->
+ TestableAlertDialog(context).also { dialog = it }
+ }
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt
index 7ecaca6c36d0..bd7e98e16b91 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt
@@ -23,23 +23,27 @@ import android.content.pm.ApplicationInfo
import android.content.pm.ServiceInfo
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
-import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.dagger.ControlsComponent
import com.android.systemui.controls.management.ControlsListingController
+import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.FakeSelectedComponentRepository
import com.android.systemui.controls.ui.SelectedItem
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import java.util.Optional
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.doReturn
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
@@ -53,16 +57,16 @@ class ControlsStartableTest : SysuiTestCase() {
@Mock private lateinit var controlsController: ControlsController
@Mock private lateinit var controlsListingController: ControlsListingController
@Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var authorizedPanelsRepository: AuthorizedPanelsRepository
+
+ private val preferredPanelsRepository = FakeSelectedComponentRepository()
private lateinit var fakeExecutor: FakeExecutor
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- context.orCreateTestableResources.addOverride(
- R.array.config_controlsPreferredPackages,
- arrayOf<String>()
- )
+ whenever(authorizedPanelsRepository.getPreferredPackages()).thenReturn(setOf())
fakeExecutor = FakeExecutor(FakeSystemClock())
}
@@ -78,107 +82,102 @@ class ControlsStartableTest : SysuiTestCase() {
fun testNoPreferredPackagesNoDefaultSelected_noNewSelection() {
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
- `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+ setUpControlsListingControls(listings)
createStartable(enabled = true).start()
+ fakeExecutor.runAllReady()
verify(controlsController, never()).setPreferredSelection(any())
}
@Test
fun testPreferredPackagesNotInstalled_noNewSelection() {
- context.orCreateTestableResources.addOverride(
- R.array.config_controlsPreferredPackages,
- arrayOf(TEST_PACKAGE_PANEL)
- )
+ whenever(authorizedPanelsRepository.getPreferredPackages())
+ .thenReturn(setOf(TEST_PACKAGE_PANEL))
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
- `when`(controlsListingController.getCurrentServices()).thenReturn(emptyList())
+ setUpControlsListingControls(emptyList())
createStartable(enabled = true).start()
+ fakeExecutor.runAllReady()
verify(controlsController, never()).setPreferredSelection(any())
}
@Test
fun testPreferredPackageNotPanel_noNewSelection() {
- context.orCreateTestableResources.addOverride(
- R.array.config_controlsPreferredPackages,
- arrayOf(TEST_PACKAGE_PANEL)
- )
+ whenever(authorizedPanelsRepository.getPreferredPackages())
+ .thenReturn(setOf(TEST_PACKAGE_PANEL))
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT, "not panel", hasPanel = false))
- `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+ setUpControlsListingControls(listings)
createStartable(enabled = true).start()
+ fakeExecutor.runAllReady()
verify(controlsController, never()).setPreferredSelection(any())
}
@Test
fun testExistingSelection_noNewSelection() {
- context.orCreateTestableResources.addOverride(
- R.array.config_controlsPreferredPackages,
- arrayOf(TEST_PACKAGE_PANEL)
- )
+ whenever(authorizedPanelsRepository.getPreferredPackages())
+ .thenReturn(setOf(TEST_PACKAGE_PANEL))
`when`(controlsController.getPreferredSelection())
.thenReturn(mock<SelectedItem.PanelItem>())
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
- `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+ setUpControlsListingControls(listings)
createStartable(enabled = true).start()
+ fakeExecutor.runAllReady()
verify(controlsController, never()).setPreferredSelection(any())
}
@Test
fun testPanelAdded() {
- context.orCreateTestableResources.addOverride(
- R.array.config_controlsPreferredPackages,
- arrayOf(TEST_PACKAGE_PANEL)
- )
+ whenever(authorizedPanelsRepository.getPreferredPackages())
+ .thenReturn(setOf(TEST_PACKAGE_PANEL))
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
- `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+ setUpControlsListingControls(listings)
createStartable(enabled = true).start()
+ fakeExecutor.runAllReady()
verify(controlsController).setPreferredSelection(listings[0].toPanelItem())
}
@Test
fun testMultiplePreferredOnlyOnePanel_panelAdded() {
- context.orCreateTestableResources.addOverride(
- R.array.config_controlsPreferredPackages,
- arrayOf("other_package", TEST_PACKAGE_PANEL)
- )
+ whenever(authorizedPanelsRepository.getPreferredPackages())
+ .thenReturn(setOf(TEST_PACKAGE_PANEL))
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
val listings =
listOf(
ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true),
ControlsServiceInfo(ComponentName("other_package", "cls"), "non panel", false)
)
- `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+ setUpControlsListingControls(listings)
createStartable(enabled = true).start()
+ fakeExecutor.runAllReady()
verify(controlsController).setPreferredSelection(listings[0].toPanelItem())
}
@Test
fun testMultiplePreferredMultiplePanels_firstPreferredAdded() {
- context.orCreateTestableResources.addOverride(
- R.array.config_controlsPreferredPackages,
- arrayOf(TEST_PACKAGE_PANEL, "other_package")
- )
+ whenever(authorizedPanelsRepository.getPreferredPackages())
+ .thenReturn(setOf(TEST_PACKAGE_PANEL))
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
val listings =
listOf(
ControlsServiceInfo(ComponentName("other_package", "cls"), "panel", true),
ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true)
)
- `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+ setUpControlsListingControls(listings)
createStartable(enabled = true).start()
+ fakeExecutor.runAllReady()
verify(controlsController).setPreferredSelection(listings[1].toPanelItem())
}
@@ -186,10 +185,11 @@ class ControlsStartableTest : SysuiTestCase() {
@Test
fun testPreferredSelectionIsPanel_bindOnStart() {
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
- `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+ setUpControlsListingControls(listings)
`when`(controlsController.getPreferredSelection()).thenReturn(listings[0].toPanelItem())
createStartable(enabled = true).start()
+ fakeExecutor.runAllReady()
verify(controlsController).bindComponentForPanel(TEST_COMPONENT_PANEL)
}
@@ -197,11 +197,12 @@ class ControlsStartableTest : SysuiTestCase() {
@Test
fun testPreferredSelectionPanel_listingNoPanel_notBind() {
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = false))
- `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+ setUpControlsListingControls(listings)
`when`(controlsController.getPreferredSelection())
.thenReturn(SelectedItem.PanelItem("panel", TEST_COMPONENT_PANEL))
createStartable(enabled = true).start()
+ fakeExecutor.runAllReady()
verify(controlsController, never()).bindComponentForPanel(any())
}
@@ -209,14 +210,35 @@ class ControlsStartableTest : SysuiTestCase() {
@Test
fun testNotPanelSelection_noBind() {
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = false))
- `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+ setUpControlsListingControls(listings)
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
createStartable(enabled = true).start()
+ fakeExecutor.runAllReady()
verify(controlsController, never()).bindComponentForPanel(any())
}
+ @Test
+ fun testAlreadyAddedPanel_noNewSelection() {
+ preferredPanelsRepository.setShouldAddDefaultComponent(false)
+ whenever(authorizedPanelsRepository.getPreferredPackages())
+ .thenReturn(setOf(TEST_PACKAGE_PANEL))
+ `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
+ val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
+ `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+
+ createStartable(enabled = true).start()
+
+ verify(controlsController, never()).setPreferredSelection(any())
+ }
+
+ private fun setUpControlsListingControls(listings: List<ControlsServiceInfo>) {
+ doAnswer { doReturn(listings).`when`(controlsListingController).getCurrentServices() }
+ .`when`(controlsListingController)
+ .forceReload()
+ }
+
private fun createStartable(enabled: Boolean): ControlsStartable {
val component: ControlsComponent =
mock() {
@@ -230,7 +252,13 @@ class ControlsStartableTest : SysuiTestCase() {
`when`(getControlsListingController()).thenReturn(Optional.empty())
}
}
- return ControlsStartable(context.resources, fakeExecutor, component, userTracker)
+ return ControlsStartable(
+ fakeExecutor,
+ component,
+ userTracker,
+ authorizedPanelsRepository,
+ preferredPanelsRepository,
+ )
}
private fun ControlsServiceInfo(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt
new file mode 100644
index 000000000000..1e8cd4117688
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt
@@ -0,0 +1,89 @@
+/*
+ * 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.controls.ui
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.FakeSystemUIDialogController
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ControlsDialogsFactoryTest : SysuiTestCase() {
+
+ private companion object {
+ const val APP_NAME = "Test App"
+ }
+
+ private val fakeDialogController = FakeSystemUIDialogController()
+
+ private lateinit var underTest: ControlsDialogsFactory
+
+ @Before
+ fun setup() {
+ underTest = ControlsDialogsFactory { fakeDialogController.dialog }
+ }
+
+ @Test
+ fun testCreatesRemoveAppDialog() {
+ val dialog = underTest.createRemoveAppDialog(context, APP_NAME) {}
+
+ verify(dialog)
+ .setTitle(
+ eq(context.getString(R.string.controls_panel_remove_app_authorization, APP_NAME))
+ )
+ verify(dialog).setCanceledOnTouchOutside(eq(true))
+ }
+
+ @Test
+ fun testPositiveClickRemoveAppDialogWorks() {
+ var dialogResult: Boolean? = null
+ underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+ fakeDialogController.clickPositive()
+
+ assertThat(dialogResult).isTrue()
+ }
+
+ @Test
+ fun testNeutralClickRemoveAppDialogWorks() {
+ var dialogResult: Boolean? = null
+ underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+ fakeDialogController.clickNeutral()
+
+ assertThat(dialogResult).isFalse()
+ }
+
+ @Test
+ fun testCancelRemoveAppDialogWorks() {
+ var dialogResult: Boolean? = null
+ underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+ fakeDialogController.cancel()
+
+ assertThat(dialogResult).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
index aa90e2a45f10..3f61bf75740a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
@@ -42,16 +42,15 @@ import com.android.systemui.controls.controller.StructureInfo
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.management.ControlsProviderSelectorActivity
import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.FakeSelectedComponentRepository
+import com.android.systemui.controls.panels.SelectedComponentRepository
import com.android.systemui.controls.settings.FakeControlsSettingsRepository
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
-import com.android.systemui.shade.ShadeController
-import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.FakeSystemUIDialogController
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
@@ -63,15 +62,12 @@ import com.android.systemui.util.time.FakeSystemClock
import com.android.wm.shell.TaskView
import com.android.wm.shell.TaskViewFactory
import com.google.common.truth.Truth.assertThat
-import dagger.Lazy
import java.util.Optional
import java.util.function.Consumer
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.anyString
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
@@ -87,24 +83,24 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
@Mock lateinit var controlsListingController: ControlsListingController
@Mock lateinit var controlActionCoordinator: ControlActionCoordinator
@Mock lateinit var activityStarter: ActivityStarter
- @Mock lateinit var shadeController: ShadeController
@Mock lateinit var iconCache: CustomIconCache
@Mock lateinit var controlsMetricsLogger: ControlsMetricsLogger
@Mock lateinit var keyguardStateController: KeyguardStateController
- @Mock lateinit var userFileManager: UserFileManager
@Mock lateinit var userTracker: UserTracker
@Mock lateinit var taskViewFactory: TaskViewFactory
@Mock lateinit var dumpManager: DumpManager
@Mock lateinit var authorizedPanelsRepository: AuthorizedPanelsRepository
@Mock lateinit var featureFlags: FeatureFlags
@Mock lateinit var packageManager: PackageManager
- val sharedPreferences = FakeSharedPreferences()
- lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
- var uiExecutor = FakeExecutor(FakeSystemClock())
- var bgExecutor = FakeExecutor(FakeSystemClock())
- lateinit var underTest: ControlsUiControllerImpl
- lateinit var parent: FrameLayout
+ private val preferredPanelRepository = FakeSelectedComponentRepository()
+ private val fakeDialogController = FakeSystemUIDialogController()
+ private val uiExecutor = FakeExecutor(FakeSystemClock())
+ private val bgExecutor = FakeExecutor(FakeSystemClock())
+
+ private lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
+ private lateinit var parent: FrameLayout
+ private lateinit var underTest: ControlsUiControllerImpl
@Before
fun setup() {
@@ -125,104 +121,41 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
underTest =
ControlsUiControllerImpl(
- Lazy { controlsController },
+ { controlsController },
context,
packageManager,
uiExecutor,
bgExecutor,
- Lazy { controlsListingController },
+ { controlsListingController },
controlActionCoordinator,
activityStarter,
iconCache,
controlsMetricsLogger,
keyguardStateController,
- userFileManager,
userTracker,
Optional.of(taskViewFactory),
controlsSettingsRepository,
authorizedPanelsRepository,
+ preferredPanelRepository,
featureFlags,
- dumpManager
- )
- `when`(
- userFileManager.getSharedPreferences(
- DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
- 0,
- 0
- )
+ ControlsDialogsFactory { fakeDialogController.dialog },
+ dumpManager,
)
- .thenReturn(sharedPreferences)
- `when`(userFileManager.getSharedPreferences(anyString(), anyInt(), anyInt()))
- .thenReturn(sharedPreferences)
`when`(userTracker.userId).thenReturn(0)
`when`(userTracker.userHandle).thenReturn(UserHandle.of(0))
}
@Test
- fun testGetPreferredStructure() {
- val structureInfo = mock<StructureInfo>()
- underTest.getPreferredSelectedItem(listOf(structureInfo))
- verify(userFileManager)
- .getSharedPreferences(
- fileName = DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
- mode = 0,
- userId = 0
- )
- }
-
- @Test
- fun testGetPreferredStructure_differentUserId() {
- val selectedItems =
- listOf(
- SelectedItem.StructureItem(
- StructureInfo(ComponentName.unflattenFromString("pkg/.cls1"), "a", ArrayList())
- ),
- SelectedItem.StructureItem(
- StructureInfo(ComponentName.unflattenFromString("pkg/.cls2"), "b", ArrayList())
- ),
- )
- val structures = selectedItems.map { it.structure }
- sharedPreferences
- .edit()
- .putString("controls_component", selectedItems[0].componentName.flattenToString())
- .putString("controls_structure", selectedItems[0].name.toString())
- .commit()
-
- val differentSharedPreferences = FakeSharedPreferences()
- differentSharedPreferences
- .edit()
- .putString("controls_component", selectedItems[1].componentName.flattenToString())
- .putString("controls_structure", selectedItems[1].name.toString())
- .commit()
-
- val previousPreferredStructure = underTest.getPreferredSelectedItem(structures)
-
- `when`(
- userFileManager.getSharedPreferences(
- DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
- 0,
- 1
- )
- )
- .thenReturn(differentSharedPreferences)
- `when`(userTracker.userId).thenReturn(1)
-
- val currentPreferredStructure = underTest.getPreferredSelectedItem(structures)
-
- assertThat(previousPreferredStructure).isEqualTo(selectedItems[0])
- assertThat(currentPreferredStructure).isEqualTo(selectedItems[1])
- assertThat(currentPreferredStructure).isNotEqualTo(previousPreferredStructure)
- }
-
- @Test
fun testGetPreferredPanel() {
val panel = SelectedItem.PanelItem("App name", ComponentName("pkg", "cls"))
- sharedPreferences
- .edit()
- .putString("controls_component", panel.componentName.flattenToString())
- .putString("controls_structure", panel.appName.toString())
- .putBoolean("controls_is_panel", true)
- .commit()
+
+ preferredPanelRepository.setSelectedComponent(
+ SelectedComponentRepository.SelectedComponent(
+ name = panel.appName.toString(),
+ componentName = panel.componentName,
+ isPanel = true,
+ )
+ )
val selected = underTest.getPreferredSelectedItem(emptyList())
@@ -366,11 +299,9 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
StructureInfo(ComponentName.unflattenFromString("pkg/.cls1"), "a", ArrayList())
),
)
- sharedPreferences
- .edit()
- .putString("controls_component", selectedItems[0].componentName.flattenToString())
- .putString("controls_structure", selectedItems[0].name.toString())
- .commit()
+ preferredPanelRepository.setSelectedComponent(
+ SelectedComponentRepository.SelectedComponent(selectedItems[0])
+ )
assertThat(underTest.resolveActivity())
.isEqualTo(ControlsProviderSelectorActivity::class.java)
@@ -410,14 +341,42 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
verify(controlsListingController, never()).removeCallback(any())
}
+ @Test
+ fun testRemovingAppsRemovesFavorite() {
+ val componentName = ComponentName(context, "cls")
+ whenever(controlsController.removeFavorites(eq(componentName))).thenReturn(true)
+ val panel = SelectedItem.PanelItem("App name", componentName)
+ preferredPanelRepository.setSelectedComponent(
+ SelectedComponentRepository.SelectedComponent(panel)
+ )
+ underTest.show(parent, {}, context)
+ underTest.startRemovingApp(componentName, "Test App")
+
+ fakeDialogController.clickPositive()
+
+ verify(controlsController).removeFavorites(eq(componentName))
+ assertThat(underTest.getPreferredSelectedItem(emptyList()))
+ .isEqualTo(SelectedItem.EMPTY_SELECTION)
+ assertThat(preferredPanelRepository.shouldAddDefaultComponent()).isFalse()
+ assertThat(preferredPanelRepository.getSelectedComponent()).isNull()
+ }
+
+ @Test
+ fun testHideCancelsTheRemoveAppDialog() {
+ val componentName = ComponentName(context, "cls")
+ underTest.show(parent, {}, context)
+ underTest.startRemovingApp(componentName, "Test App")
+
+ underTest.hide(parent)
+
+ verify(fakeDialogController.dialog).cancel()
+ }
+
private fun setUpPanel(panel: SelectedItem.PanelItem): ControlsServiceInfo {
- val activity = ComponentName("pkg", "activity")
- sharedPreferences
- .edit()
- .putString("controls_component", panel.componentName.flattenToString())
- .putString("controls_structure", panel.appName.toString())
- .putBoolean("controls_is_panel", true)
- .commit()
+ val activity = ComponentName(context, "activity")
+ preferredPanelRepository.setSelectedComponent(
+ SelectedComponentRepository.SelectedComponent(panel)
+ )
return ControlsServiceInfo(panel.componentName, panel.appName, activity)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
index dbaf94f1018c..483ab3bae6f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
@@ -37,7 +37,9 @@ class OverflowMenuAdapterTest : SysuiTestCase() {
context,
layoutId = 0,
labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
- ) { true }
+ ) {
+ true
+ }
ids.forEachIndexed { index, id -> assertThat(adapter.getItemId(index)).isEqualTo(id) }
}
@@ -51,7 +53,9 @@ class OverflowMenuAdapterTest : SysuiTestCase() {
context,
layoutId = 0,
labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
- ) { position -> position == 0 }
+ ) { position ->
+ position == 0
+ }
assertThat(adapter.isEnabled(0)).isTrue()
assertThat(adapter.isEnabled(1)).isFalse()
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 6c23254941a8..0a9470617a5f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -1,6 +1,8 @@
package com.android.systemui.dreams
+import android.animation.Animator
import android.animation.AnimatorSet
+import android.animation.ValueAnimator
import android.testing.AndroidTestingRunner
import android.view.View
import androidx.test.filters.SmallTest
@@ -10,13 +12,16 @@ import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransition
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
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
+import org.junit.Assert.assertTrue
import org.junit.Before
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.eq
@@ -71,6 +76,19 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
}
@Test
+ fun testExitAnimationUpdatesState() {
+ controller.startExitAnimations(animatorBuilder = { mockAnimator })
+
+ verify(stateController).setExitAnimationsRunning(true)
+
+ val captor = argumentCaptor<Animator.AnimatorListener>()
+ verify(mockAnimator).addListener(captor.capture())
+
+ captor.value.onAnimationEnd(mockAnimator)
+ verify(stateController).setExitAnimationsRunning(false)
+ }
+
+ @Test
fun testWakeUpCallsExecutor() {
val mockExecutor: DelayableExecutor = mock()
val mockCallback: Runnable = mock()
@@ -87,7 +105,7 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
fun testWakeUpAfterStartWillCancel() {
val mockStartAnimator: AnimatorSet = mock()
- controller.startEntryAnimations(animatorBuilder = { mockStartAnimator })
+ controller.startEntryAnimations(false, animatorBuilder = { mockStartAnimator })
verify(mockStartAnimator, never()).cancel()
@@ -100,4 +118,50 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
// animator.
verify(mockStartAnimator, times(1)).cancel()
}
+
+ @Test
+ fun testEntryAnimations_translatesUpwards() {
+ val mockStartAnimator: AnimatorSet = mock()
+
+ controller.startEntryAnimations(
+ /* downwards= */ false,
+ animatorBuilder = { mockStartAnimator }
+ )
+
+ val animatorCaptor = ArgumentCaptor.forClass(Animator::class.java)
+ verify(mockStartAnimator).playTogether(animatorCaptor.capture())
+
+ // Check if there's a ValueAnimator starting at the expected Y distance.
+ val animators: List<ValueAnimator> = animatorCaptor.allValues as List<ValueAnimator>
+ assertTrue(
+ animators.any {
+ // Call setCurrentFraction so the animated value jumps to the initial value.
+ it.setCurrentFraction(0f)
+ it.animatedValue == DREAM_IN_TRANSLATION_Y_DISTANCE.toFloat()
+ }
+ )
+ }
+
+ @Test
+ fun testEntryAnimations_translatesDownwards() {
+ val mockStartAnimator: AnimatorSet = mock()
+
+ controller.startEntryAnimations(
+ /* downwards= */ true,
+ animatorBuilder = { mockStartAnimator }
+ )
+
+ val animatorCaptor = ArgumentCaptor.forClass(Animator::class.java)
+ verify(mockStartAnimator).playTogether(animatorCaptor.capture())
+
+ // Check if there's a ValueAnimator starting at the expected Y distance.
+ val animators: List<ValueAnimator> = animatorCaptor.allValues as List<ValueAnimator>
+ assertTrue(
+ animators.any {
+ // Call setCurrentFraction so the animated value jumps to the initial value.
+ it.setCurrentFraction(0f)
+ it.animatedValue == -DREAM_IN_TRANSLATION_Y_DISTANCE.toFloat()
+ }
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index 6b095ffd3977..2a72e7d85d3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.dreams;
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;
@@ -33,6 +34,7 @@ import android.view.ViewTreeObserver;
import androidx.test.filters.SmallTest;
+import com.android.dream.lowlight.LowLightTransitionCoordinator;
import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.complication.ComplicationHostViewController;
@@ -65,6 +67,9 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
DreamOverlayStatusBarViewController mDreamOverlayStatusBarViewController;
@Mock
+ LowLightTransitionCoordinator mLowLightTransitionCoordinator;
+
+ @Mock
DreamOverlayContainerView mDreamOverlayContainerView;
@Mock
@@ -109,6 +114,7 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
mComplicationHostViewController,
mDreamOverlayContentView,
mDreamOverlayStatusBarViewController,
+ mLowLightTransitionCoordinator,
mBlurUtils,
mHandler,
mResources,
@@ -200,7 +206,7 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
mController.onViewAttached();
- verify(mAnimationsController).startEntryAnimations();
+ verify(mAnimationsController).startEntryAnimations(false);
verify(mAnimationsController, never()).cancelAnimations();
}
@@ -210,11 +216,11 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
mController.onViewAttached();
- verify(mAnimationsController, never()).startEntryAnimations();
+ verify(mAnimationsController, never()).startEntryAnimations(anyBoolean());
}
@Test
- public void testSkipEntryAnimationsWhenExitingLowLight() {
+ public void testDownwardEntryAnimationsWhenExitingLowLight() {
ArgumentCaptor<DreamOverlayStateController.Callback> callbackCaptor =
ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class);
when(mStateController.isLowLightActive()).thenReturn(false);
@@ -230,8 +236,14 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
mController.onViewAttached();
// Entry animations should be started then immediately ended to skip to the end.
- verify(mAnimationsController).startEntryAnimations();
- verify(mAnimationsController).endAnimations();
+ verify(mAnimationsController).startEntryAnimations(true);
+ }
+
+ @Test
+ public void testStartsExitAnimationsBeforeEnteringLowLight() {
+ mController.onBeforeEnterLowLight();
+
+ verify(mAnimationsController).startExitAnimations();
}
@Test
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 dfb4d5baeef5..6443621a67f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -20,6 +20,9 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
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;
@@ -59,6 +62,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -69,6 +73,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
private static final ComponentName LOW_LIGHT_COMPONENT = new ComponentName("package",
"lowlight");
private static final String DREAM_COMPONENT = "package/dream";
+ private static final String WINDOW_NAME = "test";
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private final FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
@@ -148,7 +153,8 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
mKeyguardUpdateMonitor,
mUiEventLogger,
LOW_LIGHT_COMPONENT,
- mDreamOverlayCallbackController);
+ mDreamOverlayCallbackController,
+ WINDOW_NAME);
}
public IDreamOverlayClient getClient() throws RemoteException {
@@ -190,6 +196,31 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
verify(mWindowManager).addView(any(), any());
}
+ // Validates that {@link DreamOverlayService} properly handles the case where the dream's
+ // window is no longer valid by the time start is called.
+ @Test
+ public void testInvalidWindowAddStart() throws Exception {
+ final IDreamOverlayClient client = getClient();
+
+ doThrow(new WindowManager.BadTokenException()).when(mWindowManager).addView(any(), any());
+ // Inform the overlay service of dream starting.
+ client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
+ false /*shouldShowComplication*/);
+ mMainExecutor.runAllReady();
+
+ verify(mWindowManager).addView(any(), any());
+
+ verify(mStateController).setOverlayActive(false);
+ verify(mStateController).setLowLightActive(false);
+ verify(mStateController).setEntryAnimationsFinished(false);
+
+ verify(mStateController, never()).setOverlayActive(true);
+ verify(mUiEventLogger, never()).log(
+ DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START);
+
+ verify(mDreamOverlayCallbackController, never()).onStartDream();
+ }
+
@Test
public void testDreamOverlayContainerViewControllerInitialized() throws Exception {
final IDreamOverlayClient client = getClient();
@@ -226,6 +257,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
// Inform the overlay service of dream starting.
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
true /*shouldShowComplication*/);
+ mMainExecutor.runAllReady();
assertThat(mService.shouldShowComplications()).isTrue();
}
@@ -269,6 +301,48 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
}
@Test
+ public void testImmediateEndDream() throws Exception {
+ final IDreamOverlayClient client = getClient();
+
+ // Start the dream, but don't execute any Runnables put on the executor yet. We delay
+ // executing Runnables as the timing isn't guaranteed and we want to verify that the overlay
+ // starts and finishes in the proper order even if Runnables are delayed.
+ client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
+ false /*shouldShowComplication*/);
+ // Immediately end the dream.
+ client.endDream();
+ // Run any scheduled Runnables.
+ mMainExecutor.runAllReady();
+
+ // The overlay starts then finishes.
+ InOrder inOrder = inOrder(mWindowManager);
+ inOrder.verify(mWindowManager).addView(mViewCaptor.capture(), any());
+ inOrder.verify(mWindowManager).removeView(mViewCaptor.getValue());
+ }
+
+ @Test
+ public void testEndDreamDuringStartDream() throws Exception {
+ final IDreamOverlayClient client = getClient();
+
+ // Schedule the endDream call in the middle of the startDream implementation, as any
+ // ordering is possible.
+ doAnswer(invocation -> {
+ client.endDream();
+ return null;
+ }).when(mStateController).setOverlayActive(true);
+
+ // Start the dream.
+ client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
+ false /*shouldShowComplication*/);
+ mMainExecutor.runAllReady();
+
+ // The overlay starts then finishes.
+ InOrder inOrder = inOrder(mWindowManager);
+ inOrder.verify(mWindowManager).addView(mViewCaptor.capture(), any());
+ inOrder.verify(mWindowManager).removeView(mViewCaptor.getValue());
+ }
+
+ @Test
public void testDestroy() throws RemoteException {
final IDreamOverlayClient client = getClient();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java
index dcd8736711f6..95c689737417 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java
@@ -22,6 +22,8 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.view.View;
@@ -33,6 +35,8 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.util.settings.FakeSettings;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Test;
@@ -88,14 +92,15 @@ public class ComplicationHostViewControllerTest extends SysuiTestCase {
@Captor
private ArgumentCaptor<Observer<Collection<ComplicationViewModel>>> mObserverCaptor;
- @Captor
- private ArgumentCaptor<DreamOverlayStateController.Callback> mCallbackCaptor;
-
@Complication.Category
static final int COMPLICATION_CATEGORY = Complication.CATEGORY_SYSTEM;
private ComplicationHostViewController mController;
+ private SecureSettings mSecureSettings;
+
+ private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM;
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -108,12 +113,17 @@ public class ComplicationHostViewControllerTest extends SysuiTestCase {
when(mViewHolder.getLayoutParams()).thenReturn(mComplicationLayoutParams);
when(mComplicationView.getParent()).thenReturn(mComplicationHostView);
+ mSecureSettings = new FakeSettings();
+ mSecureSettings.putFloatForUser(
+ Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f, CURRENT_USER_ID);
+
mController = new ComplicationHostViewController(
mComplicationHostView,
mLayoutEngine,
mDreamOverlayStateController,
mLifecycleOwner,
- mViewModel);
+ mViewModel,
+ mSecureSettings);
mController.init();
}
@@ -176,8 +186,6 @@ public class ComplicationHostViewControllerTest extends SysuiTestCase {
// Dream entry animations finished.
when(mDreamOverlayStateController.areEntryAnimationsFinished()).thenReturn(true);
- final DreamOverlayStateController.Callback stateCallback = captureOverlayStateCallback();
- stateCallback.onStateChanged();
// Add a complication after entry animations are finished.
final HashSet<ComplicationViewModel> complications = new HashSet<>(
@@ -188,14 +196,26 @@ public class ComplicationHostViewControllerTest extends SysuiTestCase {
verify(mComplicationView, never()).setVisibility(View.INVISIBLE);
}
+ @Test
+ public void testAnimationsDisabled_ComplicationsNeverSetToInvisible() {
+ //Disable animations
+ mController.mIsAnimationEnabled = false;
+
+ final Observer<Collection<ComplicationViewModel>> observer =
+ captureComplicationViewModelsObserver();
+
+ // Add a complication before entry animations are finished.
+ final HashSet<ComplicationViewModel> complications = new HashSet<>(
+ Collections.singletonList(mComplicationViewModel));
+ observer.onChanged(complications);
+
+ // The complication view should not be set to invisible.
+ verify(mComplicationView, never()).setVisibility(View.INVISIBLE);
+ }
+
private Observer<Collection<ComplicationViewModel>> captureComplicationViewModelsObserver() {
verify(mComplicationViewModelLiveData).observe(eq(mLifecycleOwner),
mObserverCaptor.capture());
return mObserverCaptor.getValue();
}
-
- private DreamOverlayStateController.Callback captureOverlayStateCallback() {
- verify(mDreamOverlayStateController).addCallback(mCallbackCaptor.capture());
- return mCallbackCaptor.getValue();
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
index ef62abfe36de..175da0b7a5c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
@@ -33,6 +33,8 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.condition.SelfExecutingMonitor;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.BcSmartspaceDataPlugin;
import com.android.systemui.shared.condition.Condition;
import com.android.systemui.shared.condition.Monitor;
@@ -65,6 +67,9 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
@Mock
private View mBcSmartspaceView;
+ @Mock
+ private FeatureFlags mFeatureFlags;
+
private Monitor mMonitor;
private final Set<Condition> mPreconditions = new HashSet<>();
@@ -73,6 +78,8 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
public void setup() {
MockitoAnnotations.initMocks(this);
mMonitor = SelfExecutingMonitor.createInstance();
+
+ when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(false);
}
/**
@@ -85,12 +92,22 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
verify(mDreamOverlayStateController, never()).addComplication(eq(mComplication));
}
- private SmartSpaceComplication.Registrant getRegistrant() {
- return new SmartSpaceComplication.Registrant(
- mDreamOverlayStateController,
- mComplication,
- mSmartspaceController,
- mMonitor);
+ @Test
+ public void testRegistrantStart_featureEnabled_addOverlayStateCallback() {
+ final SmartSpaceComplication.Registrant registrant = getRegistrant();
+ registrant.start();
+
+ verify(mDreamOverlayStateController).addCallback(any());
+ }
+
+ @Test
+ public void testRegistrantStart_featureDisabled_doesNotAddOverlayStateCallback() {
+ when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(true);
+
+ final SmartSpaceComplication.Registrant registrant = getRegistrant();
+ registrant.start();
+
+ verify(mDreamOverlayStateController, never()).addCallback(any());
}
@Test
@@ -188,4 +205,13 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mBcSmartspaceView);
assertEquals(viewHolder.getView(), viewHolder.getView());
}
+
+ private SmartSpaceComplication.Registrant getRegistrant() {
+ return new SmartSpaceComplication.Registrant(
+ mDreamOverlayStateController,
+ mComplication,
+ mSmartspaceController,
+ mMonitor,
+ mFeatureFlags);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
index 3a168d4e234b..d6dbd730368e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
@@ -450,6 +450,15 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
swipeToPosition(0f, Direction.DOWN, 0);
}
+ @Test
+ public void testTouchSessionOnRemovedCalledTwice() {
+ mTouchHandler.onSessionStart(mTouchSession);
+ ArgumentCaptor<DreamTouchHandler.TouchSession.Callback> onRemovedCallbackCaptor =
+ ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.Callback.class);
+ verify(mTouchSession).registerCallback(onRemovedCallbackCaptor.capture());
+ onRemovedCallbackCaptor.getValue().onRemoved();
+ onRemovedCallbackCaptor.getValue().onRemoved();
+ }
private void swipeToPosition(float percent, Direction direction, float velocityY) {
Mockito.clearInvocations(mTouchSession);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt
new file mode 100644
index 000000000000..0e14591c5f53
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt
@@ -0,0 +1,140 @@
+/*
+ * 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.flags
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.any
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+/**
+ * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()!
+ */
+@SmallTest
+class ConditionalRestarterTest : SysuiTestCase() {
+ private lateinit var restarter: ConditionalRestarter
+
+ @Mock private lateinit var systemExitRestarter: SystemExitRestarter
+
+ val restartDelayMs = 0L
+ val dispatcher = StandardTestDispatcher()
+ val testScope = TestScope(dispatcher)
+
+ val conditionA = FakeCondition()
+ val conditionB = FakeCondition()
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ restarter =
+ ConditionalRestarter(
+ systemExitRestarter,
+ setOf(conditionA, conditionB),
+ restartDelayMs,
+ testScope,
+ dispatcher
+ )
+ }
+
+ @Test
+ fun restart_ImmediatelySatisfied() =
+ testScope.runTest {
+ conditionA.canRestart = true
+ conditionB.canRestart = true
+ restarter.restartSystemUI("Restart for test")
+ advanceUntilIdle()
+ verify(systemExitRestarter).restartSystemUI(any())
+ }
+
+ @Test
+ fun restart_WaitsForConditionA() =
+ testScope.runTest {
+ conditionA.canRestart = false
+ conditionB.canRestart = true
+
+ restarter.restartSystemUI("Restart for test")
+ advanceUntilIdle()
+ // No restart occurs yet.
+ verify(systemExitRestarter, never()).restartSystemUI(any())
+
+ conditionA.canRestart = true
+ conditionA.retryFn?.invoke()
+ advanceUntilIdle()
+ verify(systemExitRestarter).restartSystemUI(any())
+ }
+
+ @Test
+ fun restart_WaitsForConditionB() =
+ testScope.runTest {
+ conditionA.canRestart = true
+ conditionB.canRestart = false
+
+ restarter.restartSystemUI("Restart for test")
+ advanceUntilIdle()
+ // No restart occurs yet.
+ verify(systemExitRestarter, never()).restartSystemUI(any())
+
+ conditionB.canRestart = true
+ conditionB.retryFn?.invoke()
+ advanceUntilIdle()
+ verify(systemExitRestarter).restartSystemUI(any())
+ }
+
+ @Test
+ fun restart_WaitsForAllConditions() =
+ testScope.runTest {
+ conditionA.canRestart = true
+ conditionB.canRestart = false
+
+ restarter.restartSystemUI("Restart for test")
+ advanceUntilIdle()
+ // No restart occurs yet.
+ verify(systemExitRestarter, never()).restartSystemUI(any())
+
+ // B becomes true, but A is now false
+ conditionA.canRestart = false
+ conditionB.canRestart = true
+ conditionB.retryFn?.invoke()
+ advanceUntilIdle()
+ // No restart occurs yet.
+ verify(systemExitRestarter, never()).restartSystemUI(any())
+
+ conditionA.canRestart = true
+ conditionA.retryFn?.invoke()
+ advanceUntilIdle()
+ verify(systemExitRestarter).restartSystemUI(any())
+ }
+
+ class FakeCondition : ConditionalRestarter.Condition {
+ var retryFn: (() -> Unit)? = null
+ var canRestart = false
+
+ override fun canRestartNow(retryFn: () -> Unit): Boolean {
+ this.retryFn = retryFn
+
+ return canRestart
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseRestarterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseRestarterTest.kt
deleted file mode 100644
index 6060afe495f5..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseRestarterTest.kt
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.flags
-
-import android.test.suitebuilder.annotation.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.keyguard.WakefulnessLifecycle
-import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP
-import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE
-import com.android.systemui.statusbar.policy.BatteryController
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.mockito.ArgumentCaptor
-import org.mockito.Mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-/**
- * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()!
- */
-@SmallTest
-class FeatureFlagsReleaseRestarterTest : SysuiTestCase() {
- private lateinit var restarter: FeatureFlagsReleaseRestarter
-
- @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
- @Mock private lateinit var batteryController: BatteryController
- @Mock private lateinit var systemExitRestarter: SystemExitRestarter
- private val executor = FakeExecutor(FakeSystemClock())
-
- @Before
- fun setup() {
- MockitoAnnotations.initMocks(this)
- restarter =
- FeatureFlagsReleaseRestarter(
- wakefulnessLifecycle,
- batteryController,
- executor,
- systemExitRestarter
- )
- }
-
- @Test
- fun testRestart_ScheduledWhenReady() {
- whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
- whenever(batteryController.isPluggedIn).thenReturn(true)
-
- assertThat(executor.numPending()).isEqualTo(0)
- restarter.restartSystemUI("Restart for test")
- assertThat(executor.numPending()).isEqualTo(1)
- }
-
- @Test
- fun testRestart_RestartsWhenIdle() {
- whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
- whenever(batteryController.isPluggedIn).thenReturn(true)
-
- restarter.restartSystemUI("Restart for test")
- verify(systemExitRestarter, never()).restartSystemUI("Restart for test")
- executor.advanceClockToLast()
- executor.runAllReady()
- verify(systemExitRestarter).restartSystemUI(any())
- }
-
- @Test
- fun testRestart_NotScheduledWhenAwake() {
- whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
- whenever(batteryController.isPluggedIn).thenReturn(true)
-
- assertThat(executor.numPending()).isEqualTo(0)
- restarter.restartSystemUI("Restart for test")
- assertThat(executor.numPending()).isEqualTo(0)
- }
-
- @Test
- fun testRestart_NotScheduledWhenNotPluggedIn() {
- whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
- whenever(batteryController.isPluggedIn).thenReturn(false)
-
- assertThat(executor.numPending()).isEqualTo(0)
- restarter.restartSystemUI("Restart for test")
- assertThat(executor.numPending()).isEqualTo(0)
- }
-
- @Test
- fun testRestart_NotDoubleSheduled() {
- whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
- whenever(batteryController.isPluggedIn).thenReturn(true)
-
- assertThat(executor.numPending()).isEqualTo(0)
- restarter.restartSystemUI("Restart for test")
- restarter.restartSystemUI("Restart for test")
- assertThat(executor.numPending()).isEqualTo(1)
- }
-
- @Test
- fun testWakefulnessLifecycle_CanRestart() {
- whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
- whenever(batteryController.isPluggedIn).thenReturn(true)
- assertThat(executor.numPending()).isEqualTo(0)
- restarter.restartSystemUI("Restart for test")
-
- val captor = ArgumentCaptor.forClass(WakefulnessLifecycle.Observer::class.java)
- verify(wakefulnessLifecycle).addObserver(captor.capture())
-
- whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
-
- captor.value.onFinishedGoingToSleep()
- assertThat(executor.numPending()).isEqualTo(1)
- }
-
- @Test
- fun testBatteryController_CanRestart() {
- whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
- whenever(batteryController.isPluggedIn).thenReturn(false)
- assertThat(executor.numPending()).isEqualTo(0)
- restarter.restartSystemUI("Restart for test")
-
- val captor =
- ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback::class.java)
- verify(batteryController).addCallback(captor.capture())
-
- whenever(batteryController.isPluggedIn).thenReturn(true)
-
- captor.value.onBatteryLevelChanged(0, true, true)
- assertThat(executor.numPending()).isEqualTo(1)
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt
new file mode 100644
index 000000000000..647b05a77b90
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.flags
+
+import android.test.suitebuilder.annotation.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.policy.BatteryController
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+/**
+ * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()!
+ */
+@SmallTest
+class PluggedInConditionTest : SysuiTestCase() {
+ private lateinit var condition: PluggedInCondition
+
+ @Mock private lateinit var batteryController: BatteryController
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ condition = PluggedInCondition(batteryController)
+ }
+
+ @Test
+ fun testCondition_unplugged() {
+ whenever(batteryController.isPluggedIn).thenReturn(false)
+
+ assertThat(condition.canRestartNow({})).isFalse()
+ }
+
+ @Test
+ fun testCondition_pluggedIn() {
+ whenever(batteryController.isPluggedIn).thenReturn(true)
+
+ assertThat(condition.canRestartNow({})).isTrue()
+ }
+
+ @Test
+ fun testCondition_invokesRetry() {
+ whenever(batteryController.isPluggedIn).thenReturn(false)
+ var retried = false
+ val retryFn = { retried = true }
+
+ // No restart yet, but we do register a listener now.
+ assertThat(condition.canRestartNow(retryFn)).isFalse()
+ val captor =
+ ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback::class.java)
+ verify(batteryController).addCallback(captor.capture())
+
+ whenever(batteryController.isPluggedIn).thenReturn(true)
+
+ captor.value.onBatteryLevelChanged(0, true, true)
+ assertThat(retried).isTrue()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugRestarterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
index 686782f59355..f7a773ea30ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugRestarterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,12 +20,11 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP
import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE
-import com.android.systemui.util.mockito.any
+import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentCaptor
import org.mockito.Mock
-import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@@ -34,37 +33,45 @@ import org.mockito.MockitoAnnotations
* Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()!
*/
@SmallTest
-class FeatureFlagsDebugRestarterTest : SysuiTestCase() {
- private lateinit var restarter: FeatureFlagsDebugRestarter
+class ScreenIdleConditionTest : SysuiTestCase() {
+ private lateinit var condition: ScreenIdleCondition
@Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
- @Mock private lateinit var systemExitRestarter: SystemExitRestarter
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- restarter = FeatureFlagsDebugRestarter(wakefulnessLifecycle, systemExitRestarter)
+ condition = ScreenIdleCondition(wakefulnessLifecycle)
}
@Test
- fun testRestart_ImmediateWhenAsleep() {
+ fun testCondition_awake() {
+ whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
+
+ assertThat(condition.canRestartNow {}).isFalse()
+ }
+
+ @Test
+ fun testCondition_asleep() {
whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
- restarter.restartSystemUI("Restart for test")
- verify(systemExitRestarter).restartSystemUI(any())
+
+ assertThat(condition.canRestartNow {}).isTrue()
}
@Test
- fun testRestart_WaitsForSceenOff() {
+ fun testCondition_invokesRetry() {
whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
+ var retried = false
+ val retryFn = { retried = true }
- restarter.restartSystemUI("Restart for test")
- verify(systemExitRestarter, never()).restartSystemUI(any())
-
+ // No restart yet, but we do register a listener now.
+ assertThat(condition.canRestartNow(retryFn)).isFalse()
val captor = ArgumentCaptor.forClass(WakefulnessLifecycle.Observer::class.java)
verify(wakefulnessLifecycle).addObserver(captor.capture())
- captor.value.onFinishedGoingToSleep()
+ whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
- verify(systemExitRestarter).restartSystemUI(any())
+ captor.value.onFinishedGoingToSleep()
+ assertThat(retried).isTrue()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
index a12315b63fa7..2e9800606edf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
@@ -26,6 +26,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -58,4 +59,16 @@ class ServerFlagReaderImplTest : SysuiTestCase() {
verify(changeListener).onChange(flag)
}
+
+ @Test
+ fun testChange_ignoresListenersDuringTest() {
+ val serverFlagReader = ServerFlagReaderImpl(NAMESPACE, deviceConfig, executor, true)
+ val flag = ReleasedFlag(1, "1", "test")
+ serverFlagReader.listenForChanges(listOf(flag), changeListener)
+
+ deviceConfig.setProperty(NAMESPACE, "flag_override_1", "1", false)
+ executor.runAllReady()
+
+ verify(changeListener, never()).onChange(flag)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt
new file mode 100644
index 000000000000..ec94cdec78f0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.keyboard.backlight.domain.interactor
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
+import com.android.systemui.keyboard.shared.model.BacklightModel
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyboardBacklightInteractorTest : SysuiTestCase() {
+
+ private val keyboardRepository = FakeKeyboardRepository()
+ private lateinit var underTest: KeyboardBacklightInteractor
+
+ @Before
+ fun setUp() {
+ underTest = KeyboardBacklightInteractor(keyboardRepository)
+ }
+
+ @Test
+ fun emitsNull_whenKeyboardJustConnected() = runTest {
+ val latest by collectLastValue(underTest.backlight)
+ keyboardRepository.setKeyboardConnected(true)
+
+ assertThat(latest).isNull()
+ }
+
+ @Test
+ fun emitsBacklight_whenKeyboardConnectedAndBacklightChanged() = runTest {
+ keyboardRepository.setKeyboardConnected(true)
+ keyboardRepository.setBacklight(BacklightModel(1, 5))
+
+ assertThat(underTest.backlight.first()).isEqualTo(BacklightModel(1, 5))
+ }
+
+ @Test
+ fun emitsNull_afterKeyboardDisconnecting() = runTest {
+ val latest by collectLastValue(underTest.backlight)
+ keyboardRepository.setKeyboardConnected(true)
+ keyboardRepository.setBacklight(BacklightModel(1, 5))
+
+ keyboardRepository.setKeyboardConnected(false)
+
+ assertThat(latest).isNull()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModelTest.kt
new file mode 100644
index 000000000000..ec05d10b793c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModelTest.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyboard.backlight.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyboard.backlight.domain.interactor.KeyboardBacklightInteractor
+import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
+import com.android.systemui.keyboard.shared.model.BacklightModel
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class BacklightDialogViewModelTest : SysuiTestCase() {
+
+ private val keyboardRepository = FakeKeyboardRepository()
+ private lateinit var underTest: BacklightDialogViewModel
+ @Mock private lateinit var accessibilityManagerWrapper: AccessibilityManagerWrapper
+ private val timeoutMillis = 3000L
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(accessibilityManagerWrapper.getRecommendedTimeoutMillis(any(), any()))
+ .thenReturn(timeoutMillis.toInt())
+ underTest =
+ BacklightDialogViewModel(
+ KeyboardBacklightInteractor(keyboardRepository),
+ accessibilityManagerWrapper
+ )
+ keyboardRepository.setKeyboardConnected(true)
+ }
+
+ @Test
+ fun emitsViewModel_whenBacklightChanged() = runTest {
+ keyboardRepository.setBacklight(BacklightModel(1, 5))
+
+ assertThat(underTest.dialogContent.first()).isEqualTo(BacklightDialogContentViewModel(1, 5))
+ }
+
+ @Test
+ fun emitsNull_afterTimeout() = runTest {
+ val latest by collectLastValue(underTest.dialogContent)
+ keyboardRepository.setBacklight(BacklightModel(1, 5))
+
+ assertThat(latest).isEqualTo(BacklightDialogContentViewModel(1, 5))
+ advanceTimeBy(timeoutMillis + 1)
+ assertThat(latest).isNull()
+ }
+
+ @Test
+ fun emitsNull_after5secDelay_fromLastBacklightChange() = runTest {
+ val latest by collectLastValue(underTest.dialogContent)
+ keyboardRepository.setKeyboardConnected(true)
+
+ keyboardRepository.setBacklight(BacklightModel(1, 5))
+ assertThat(latest).isEqualTo(BacklightDialogContentViewModel(1, 5))
+
+ advanceTimeBy(timeoutMillis * 2 / 3)
+ // timeout yet to pass, no new emission
+ keyboardRepository.setBacklight(BacklightModel(2, 5))
+ assertThat(latest).isEqualTo(BacklightDialogContentViewModel(2, 5))
+
+ advanceTimeBy(timeoutMillis * 2 / 3)
+ // timeout refreshed because of last `setBacklight`, still content present
+ assertThat(latest).isEqualTo(BacklightDialogContentViewModel(2, 5))
+
+ advanceTimeBy(timeoutMillis * 2 / 3)
+ // finally timeout reached and null emitted
+ assertThat(latest).isNull()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
new file mode 100644
index 000000000000..f6ff4b214035
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
@@ -0,0 +1,191 @@
+/*
+ * 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.keyboard.data.repository
+
+import android.hardware.input.InputManager
+import android.view.InputDevice
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.nullable
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyboardRepositoryTest : SysuiTestCase() {
+
+ @Captor
+ private lateinit var deviceListenerCaptor: ArgumentCaptor<InputManager.InputDeviceListener>
+ @Mock private lateinit var inputManager: InputManager
+
+ private lateinit var underTest: KeyboardRepository
+ private lateinit var dispatcher: CoroutineDispatcher
+ private lateinit var testScope: TestScope
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf())
+ whenever(inputManager.getInputDevice(any())).then { invocation ->
+ val id = invocation.arguments.first()
+ INPUT_DEVICES_MAP[id]
+ }
+ dispatcher = StandardTestDispatcher()
+ testScope = TestScope(dispatcher)
+ underTest = KeyboardRepositoryImpl(testScope.backgroundScope, dispatcher, inputManager)
+ }
+
+ @Test
+ fun emitsDisconnected_ifNothingIsConnected() =
+ testScope.runTest {
+ val initialState = underTest.keyboardConnected.first()
+ assertThat(initialState).isFalse()
+ }
+
+ @Test
+ fun emitsConnected_ifKeyboardAlreadyConnectedAtTheStart() =
+ testScope.runTest {
+ whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(PHYSICAL_FULL_KEYBOARD_ID))
+ val initialValue = underTest.keyboardConnected.first()
+ assertThat(initialValue).isTrue()
+ }
+
+ @Test
+ fun emitsConnected_whenNewPhysicalKeyboardConnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun emitsDisconnected_whenKeyboardDisconnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isTrue()
+
+ deviceListener.onInputDeviceRemoved(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ private suspend fun captureDeviceListener(): InputManager.InputDeviceListener {
+ underTest.keyboardConnected.first()
+ verify(inputManager).registerInputDeviceListener(deviceListenerCaptor.capture(), nullable())
+ return deviceListenerCaptor.value
+ }
+
+ @Test
+ fun emitsDisconnected_whenVirtualOrNotFullKeyboardConnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_NOT_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+
+ deviceListener.onInputDeviceAdded(VIRTUAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ @Test
+ fun emitsDisconnected_whenKeyboardDisconnectsAndWasAlreadyConnectedAtTheStart() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceRemoved(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ @Test
+ fun emitsConnected_whenAnotherDeviceDisconnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceRemoved(VIRTUAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun emitsConnected_whenOnePhysicalKeyboardDisconnectsButAnotherRemainsConnected() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceAdded(ANOTHER_PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceRemoved(ANOTHER_PHYSICAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun passesKeyboardBacklightValues_fromBacklightListener() {
+ // TODO(b/268645734): implement when implementing backlight listener
+ }
+
+ private companion object {
+ private const val PHYSICAL_FULL_KEYBOARD_ID = 1
+ private const val VIRTUAL_FULL_KEYBOARD_ID = 2
+ private const val PHYSICAL_NOT_FULL_KEYBOARD_ID = 3
+ private const val ANOTHER_PHYSICAL_FULL_KEYBOARD_ID = 4
+
+ private val INPUT_DEVICES_MAP: Map<Int, InputDevice> =
+ mapOf(
+ PHYSICAL_FULL_KEYBOARD_ID to inputDevice(virtual = false, fullKeyboard = true),
+ VIRTUAL_FULL_KEYBOARD_ID to inputDevice(virtual = true, fullKeyboard = true),
+ PHYSICAL_NOT_FULL_KEYBOARD_ID to inputDevice(virtual = false, fullKeyboard = false),
+ ANOTHER_PHYSICAL_FULL_KEYBOARD_ID to
+ inputDevice(virtual = false, fullKeyboard = true)
+ )
+
+ private fun inputDevice(virtual: Boolean, fullKeyboard: Boolean): InputDevice =
+ mock<InputDevice>().also {
+ whenever(it.isVirtual).thenReturn(virtual)
+ whenever(it.isFullKeyboard).thenReturn(fullKeyboard)
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
index a4e5bcaecde4..3accefddd32a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -189,6 +189,7 @@ class CustomizationProviderTest : SysuiTestCase() {
)
underTest.previewManager =
KeyguardRemotePreviewManager(
+ applicationScope = testScope.backgroundScope,
previewRendererFactory = previewRendererFactory,
mainDispatcher = testDispatcher,
backgroundHandler = backgroundHandler,
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 f55b86686152..c93e677071cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -29,7 +29,6 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -67,7 +66,6 @@ import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
@@ -137,7 +135,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock AuthController mAuthController;
private @Mock ShadeExpansionStateManager mShadeExpansionStateManager;
private @Mock ShadeWindowLogger mShadeWindowLogger;
- private @Mock FeatureFlags mFeatureFlags;
private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -545,7 +542,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mScreenOnCoordinator,
mInteractionJankMonitor,
mDreamOverlayStateController,
- mFeatureFlags,
() -> mShadeController,
() -> mNotificationShadeWindowController,
() -> mActivityLaunchAnimator,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
index 21ad5e2cd311..5dc04f7efa63 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
@@ -30,6 +30,7 @@ import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.coroutines.collectLastValue
@@ -38,11 +39,14 @@ import com.android.systemui.keyguard.data.repository.BiometricType.FACE
import com.android.systemui.keyguard.data.repository.BiometricType.REAR_FINGERPRINT
import com.android.systemui.keyguard.data.repository.BiometricType.SIDE_FINGERPRINT
import com.android.systemui.keyguard.data.repository.BiometricType.UNDER_DISPLAY_FINGERPRINT
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.TestScope
@@ -62,6 +66,7 @@ import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidTestingRunner::class)
@@ -78,6 +83,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() {
private lateinit var biometricManagerCallback:
ArgumentCaptor<IBiometricEnabledOnKeyguardCallback.Stub>
private lateinit var userRepository: FakeUserRepository
+ private lateinit var devicePostureRepository: FakeDevicePostureRepository
private lateinit var testDispatcher: TestDispatcher
private lateinit var testScope: TestScope
@@ -90,6 +96,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() {
testDispatcher = StandardTestDispatcher()
testScope = TestScope(testDispatcher)
userRepository = FakeUserRepository()
+ devicePostureRepository = FakeDevicePostureRepository()
}
private suspend fun createBiometricSettingsRepository() {
@@ -108,6 +115,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() {
looper = testableLooper!!.looper,
dumpManager = dumpManager,
biometricManager = biometricManager,
+ devicePostureRepository = devicePostureRepository,
)
testScope.runCurrent()
}
@@ -299,6 +307,50 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() {
verify(biometricManager, times(1)).registerEnabledOnKeyguardCallback(any())
}
+ @Test
+ fun faceAuthIsAlwaysSupportedIfSpecificPostureIsNotConfigured() =
+ testScope.runTest {
+ overrideResource(
+ R.integer.config_face_auth_supported_posture,
+ DevicePostureController.DEVICE_POSTURE_UNKNOWN
+ )
+
+ createBiometricSettingsRepository()
+
+ assertThat(collectLastValue(underTest.isFaceAuthSupportedInCurrentPosture)()).isTrue()
+ }
+
+ @Test
+ fun faceAuthIsSupportedOnlyWhenDevicePostureMatchesConfigValue() =
+ testScope.runTest {
+ overrideResource(
+ R.integer.config_face_auth_supported_posture,
+ DevicePostureController.DEVICE_POSTURE_FLIPPED
+ )
+
+ createBiometricSettingsRepository()
+
+ val isFaceAuthSupported =
+ collectLastValue(underTest.isFaceAuthSupportedInCurrentPosture)
+
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.CLOSED)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.HALF_OPENED)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.OPENED)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.UNKNOWN)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.FLIPPED)
+ assertThat(isFaceAuthSupported()).isTrue()
+ }
+
private fun enrollmentChange(biometricType: BiometricType, userId: Int, enabled: Boolean) {
authControllerCallback.value.onEnrollmentsChanged(biometricType, userId, enabled)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
new file mode 100644
index 000000000000..bd6b7a853dfc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
@@ -0,0 +1,80 @@
+/*
+ * 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.keyguard.data.repository
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class DevicePostureRepositoryTest : SysuiTestCase() {
+ private lateinit var underTest: DevicePostureRepository
+ private lateinit var testScope: TestScope
+ @Mock private lateinit var devicePostureController: DevicePostureController
+ @Captor private lateinit var callback: ArgumentCaptor<DevicePostureController.Callback>
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ testScope = TestScope()
+ underTest = DevicePostureRepositoryImpl(postureController = devicePostureController)
+ }
+
+ @Test
+ fun postureChangesArePropagated() =
+ testScope.runTest {
+ whenever(devicePostureController.devicePosture)
+ .thenReturn(DevicePostureController.DEVICE_POSTURE_FLIPPED)
+ val currentPosture = collectLastValue(underTest.currentDevicePosture)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.FLIPPED)
+
+ verify(devicePostureController).addCallback(callback.capture())
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_UNKNOWN)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.UNKNOWN)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_CLOSED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.CLOSED)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_HALF_OPENED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.HALF_OPENED)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_OPENED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.OPENED)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_FLIPPED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.FLIPPED)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
index ff22f1e0a52a..4e7b3b91550d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
@@ -55,7 +55,7 @@ class KeyguardBouncerRepositoryTest : SysuiTestCase() {
@Test
fun changingFlowValueTriggersLogging() = runBlocking {
- underTest.setPrimaryHide(true)
- verify(bouncerLogger).logChange("", "PrimaryBouncerHide", false)
+ underTest.setPrimaryShow(true)
+ verify(bouncerLogger).logChange("", "PrimaryBouncerShow", false)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 0469e77ca991..0e6f8d4e0720 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -219,6 +219,29 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
}
@Test
+ fun isKeyguardUnlocked() =
+ runTest(UnconfinedTestDispatcher()) {
+ whenever(keyguardStateController.isUnlocked).thenReturn(false)
+ var latest: Boolean? = null
+ val job = underTest.isKeyguardUnlocked.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isFalse()
+
+ val captor = argumentCaptor<KeyguardStateController.Callback>()
+ verify(keyguardStateController).addCallback(captor.capture())
+
+ whenever(keyguardStateController.isUnlocked).thenReturn(true)
+ captor.value.onUnlockedChanged()
+ assertThat(latest).isTrue()
+
+ whenever(keyguardStateController.isUnlocked).thenReturn(false)
+ captor.value.onUnlockedChanged()
+ assertThat(latest).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
fun isDozing() =
runTest(UnconfinedTestDispatcher()) {
var latest: Boolean? = null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
index ae227b4b8370..d9d4013b09b9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -21,6 +21,7 @@ import android.util.Log
import android.util.Log.TerribleFailure
import android.util.Log.TerribleFailureHandler
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Interpolators
@@ -47,6 +48,7 @@ import org.junit.runner.RunWith
@SmallTest
@RunWith(AndroidJUnit4::class)
+@FlakyTest(bugId = 270760395)
class KeyguardTransitionRepositoryTest : SysuiTestCase() {
private lateinit var underTest: KeyguardTransitionRepository
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
index d2db910ad443..f9493d10ff61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
@@ -62,7 +62,9 @@ class LightRevealScrimRepositoryTest : SysuiTestCase() {
fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
runCurrent()
- values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ )
// We got a source but still have no sensor locations, so should be sticking with
// the default effect.
@@ -71,14 +73,18 @@ class LightRevealScrimRepositoryTest : SysuiTestCase() {
)
runCurrent()
- values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ )
// We got a location for the face sensor, but we unlocked with fingerprint.
val faceLocation = Point(250, 0)
fakeKeyguardRepository.setFaceSensorLocation(faceLocation)
runCurrent()
- values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ )
// Now we have fingerprint sensor locations, and wake and unlock via fingerprint.
val fingerprintLocation = Point(500, 500)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
index 18e80ea40c5c..1365132d6dac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
@@ -28,6 +28,8 @@ import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintA
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepositoryImpl
import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.SystemClock
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -50,6 +52,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
private lateinit var deviceEntryFingerprintAuthRepository:
FakeDeviceEntryFingerprintAuthRepository
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var systemClock: SystemClock
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var bouncerLogger: TableLogBuffer
@@ -70,6 +73,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
featureFlags = FakeFeatureFlags().apply { this.set(Flags.MODERN_ALTERNATE_BOUNCER, true) }
underTest =
AlternateBouncerInteractor(
+ keyguardStateController,
bouncerRepository,
biometricSettingsRepository,
deviceEntryFingerprintAuthRepository,
@@ -134,6 +138,14 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
}
@Test
+ fun canShowAlternateBouncerForFingerprint_butCanDismissLockScreen() {
+ givenCanShowAlternateBouncer()
+ whenever(keyguardStateController.isUnlocked).thenReturn(true)
+
+ assertFalse(underTest.canShowAlternateBouncerForFingerprint())
+ }
+
+ @Test
fun show_whenCannotShow() {
givenCannotShowAlternateBouncer()
@@ -163,6 +175,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
biometricSettingsRepository.setStrongBiometricAllowed(true)
biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(true)
deviceEntryFingerprintAuthRepository.setLockedOut(false)
+ whenever(keyguardStateController.isUnlocked).thenReturn(false)
}
private fun givenCannotShowAlternateBouncer() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 153439e4fe07..7f3016270def 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -145,7 +145,7 @@ class KeyguardInteractorTest : SysuiTestCase() {
repository.setKeyguardOccluded(true)
assertThat(secureCameraActive()).isTrue()
- bouncerRepository.setPrimaryVisible(true)
+ bouncerRepository.setPrimaryShow(true)
assertThat(secureCameraActive()).isFalse()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index 62c9e5ffbb51..5528b94a691c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -281,6 +281,24 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
}
@Test
+ fun `quickAffordance - hidden when quick settings is visible`() =
+ testScope.runTest {
+ repository.setQuickSettingsVisible(true)
+ quickAccessWallet.setState(
+ KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+ icon = ICON,
+ )
+ )
+
+ val collectedValue =
+ collectLastValue(
+ underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END)
+ )
+
+ assertThat(collectedValue()).isEqualTo(KeyguardQuickAffordanceModel.Hidden)
+ }
+
+ @Test
fun `quickAffordance - bottom start affordance hidden while dozing`() =
testScope.runTest {
repository.setDozing(true)
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 ae7a928cdb2c..092fdca6fd41 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
@@ -19,6 +19,8 @@ package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
import androidx.test.filters.FlakyTest
import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Interpolators
import com.android.systemui.flags.FakeFeatureFlags
@@ -40,6 +42,7 @@ import com.android.systemui.keyguard.util.KeyguardTransitionRunner
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.mockito.withArgCaptor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.cancelChildren
@@ -51,6 +54,8 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
@@ -77,6 +82,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
// Used to verify transition requests for test output
@Mock private lateinit var mockTransitionRepository: KeyguardTransitionRepository
@Mock private lateinit var commandQueue: CommandQueue
+ @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
private lateinit var fromDreamingTransitionInteractor: FromDreamingTransitionInteractor
@@ -102,6 +108,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
transitionRepository = KeyguardTransitionRepositoryImpl()
runner = KeyguardTransitionRunner(transitionRepository)
+ whenever(keyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(PIN)
+
val featureFlags = FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, true) }
fromLockscreenTransitionInteractor =
FromLockscreenTransitionInteractor(
@@ -173,16 +181,17 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardTransitionRepository = mockTransitionRepository,
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ keyguardSecurityModel = keyguardSecurityModel,
)
fromPrimaryBouncerTransitionInteractor.start()
}
@Test
- fun `DREAMING to LOCKSCREEN - dreaming state changes first`() =
+ fun `DREAMING to LOCKSCREEN`() =
testScope.runTest {
- // GIVEN a device is dreaming and occluded
+ // GIVEN a device is dreaming
keyguardRepository.setDreamingWithOverlay(true)
- keyguardRepository.setKeyguardOccluded(true)
+ keyguardRepository.setWakefulnessModel(startingToWake())
runCurrent()
// GIVEN a prior transition has run to DREAMING
@@ -215,56 +224,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
- }
- // 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 `DREAMING to LOCKSCREEN - occluded state changes first`() =
- testScope.runTest {
- // GIVEN a device is dreaming and occluded
- keyguardRepository.setDreamingWithOverlay(true)
- keyguardRepository.setKeyguardOccluded(true)
- runCurrent()
-
- // GIVEN a prior transition has run to DREAMING
- runner.startTransition(
- testScope,
- TransitionInfo(
- ownerName = "",
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.DREAMING,
- animator =
- ValueAnimator().apply {
- duration = 10
- interpolator = Interpolators.LINEAR
- },
- )
- )
- runCurrent()
- reset(mockTransitionRepository)
-
- // WHEN doze is complete
- keyguardRepository.setDozeTransitionModel(
- DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
- )
- // AND occluded has stopped
- keyguardRepository.setKeyguardOccluded(false)
- advanceUntilIdle()
- // AND then dreaming has stopped
- keyguardRepository.setDreamingWithOverlay(false)
- advanceUntilIdle()
-
- val info =
- withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to BOUNCER should occur
assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
@@ -299,12 +259,12 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
runCurrent()
// WHEN the primary bouncer is set to show
- bouncerRepository.setPrimaryVisible(true)
+ bouncerRepository.setPrimaryShow(true)
runCurrent()
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to PRIMARY_BOUNCER should occur
assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -345,7 +305,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to DOZING should occur
assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -386,7 +346,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to DOZING should occur
assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -398,6 +358,50 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
+ fun `LOCKSCREEN to DREAMING`() =
+ testScope.runTest {
+ // GIVEN a device that is not dreaming or dozing
+ keyguardRepository.setDreamingWithOverlay(false)
+ keyguardRepository.setWakefulnessModel(startingToWake())
+ keyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
+ )
+ runCurrent()
+
+ // GIVEN a prior transition has run to LOCKSCREEN
+ runner.startTransition(
+ testScope,
+ TransitionInfo(
+ ownerName = "",
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ animator =
+ ValueAnimator().apply {
+ duration = 10
+ interpolator = Interpolators.LINEAR
+ },
+ )
+ )
+ reset(mockTransitionRepository)
+
+ // WHEN the device begins to dream
+ keyguardRepository.setDreamingWithOverlay(true)
+ advanceUntilIdle()
+
+ val info =
+ withArgCaptor<TransitionInfo> {
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
+ }
+ // THEN a transition to DREAMING should occur
+ assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
+ assertThat(info.from).isEqualTo(KeyguardState.LOCKSCREEN)
+ assertThat(info.to).isEqualTo(KeyguardState.DREAMING)
+ assertThat(info.animator).isNotNull()
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
fun `LOCKSCREEN to DOZING`() =
testScope.runTest {
// GIVEN a device with AOD not available
@@ -427,7 +431,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to DOZING should occur
assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -468,7 +472,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to DOZING should occur
assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -505,7 +509,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to DOZING should occur
assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
@@ -542,7 +546,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to DOZING should occur
assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
@@ -583,7 +587,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to DOZING should occur
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -624,7 +628,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to AOD should occur
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -661,7 +665,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to AOD should occur
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -677,6 +681,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
testScope.runTest {
// GIVEN a device that is not dreaming or dozing
keyguardRepository.setDreamingWithOverlay(false)
+ keyguardRepository.setWakefulnessModel(startingToWake())
keyguardRepository.setDozeTransitionModel(
DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
)
@@ -704,7 +709,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to DREAMING should occur
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -736,12 +741,12 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
reset(mockTransitionRepository)
// WHEN the alternateBouncer stops showing and then the primary bouncer shows
- bouncerRepository.setPrimaryVisible(true)
+ bouncerRepository.setPrimaryShow(true)
runCurrent()
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to PRIMARY_BOUNCER should occur
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -774,7 +779,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
reset(mockTransitionRepository)
// GIVEN the primary bouncer isn't showing, aod available and starting to sleep
- bouncerRepository.setPrimaryVisible(false)
+ bouncerRepository.setPrimaryShow(false)
keyguardRepository.setAodAvailable(true)
keyguardRepository.setWakefulnessModel(startingToSleep())
@@ -784,7 +789,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to AOD should occur
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -818,7 +823,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
// GIVEN the primary bouncer isn't showing, aod not available and starting to sleep
// to sleep
- bouncerRepository.setPrimaryVisible(false)
+ bouncerRepository.setPrimaryShow(false)
keyguardRepository.setAodAvailable(false)
keyguardRepository.setWakefulnessModel(startingToSleep())
@@ -828,7 +833,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to DOZING should occur
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -861,7 +866,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
reset(mockTransitionRepository)
// GIVEN the primary bouncer isn't showing and device not sleeping
- bouncerRepository.setPrimaryVisible(false)
+ bouncerRepository.setPrimaryShow(false)
keyguardRepository.setWakefulnessModel(startingToWake())
// WHEN the alternateBouncer stops showing
@@ -870,7 +875,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to LOCKSCREEN should occur
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -885,7 +890,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fun `PRIMARY_BOUNCER to AOD`() =
testScope.runTest {
// GIVEN a prior transition has run to PRIMARY_BOUNCER
- bouncerRepository.setPrimaryVisible(true)
+ bouncerRepository.setPrimaryShow(true)
runner.startTransition(
testScope,
TransitionInfo(
@@ -907,12 +912,12 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(startingToSleep())
// WHEN the primaryBouncer stops showing
- bouncerRepository.setPrimaryVisible(false)
+ bouncerRepository.setPrimaryShow(false)
runCurrent()
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to AOD should occur
assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -927,7 +932,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fun `PRIMARY_BOUNCER to DOZING`() =
testScope.runTest {
// GIVEN a prior transition has run to PRIMARY_BOUNCER
- bouncerRepository.setPrimaryVisible(true)
+ bouncerRepository.setPrimaryShow(true)
runner.startTransition(
testScope,
TransitionInfo(
@@ -949,12 +954,12 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(startingToSleep())
// WHEN the primaryBouncer stops showing
- bouncerRepository.setPrimaryVisible(false)
+ bouncerRepository.setPrimaryShow(false)
runCurrent()
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to DOZING should occur
assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -969,7 +974,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fun `PRIMARY_BOUNCER to LOCKSCREEN`() =
testScope.runTest {
// GIVEN a prior transition has run to PRIMARY_BOUNCER
- bouncerRepository.setPrimaryVisible(true)
+ bouncerRepository.setPrimaryShow(true)
runner.startTransition(
testScope,
TransitionInfo(
@@ -990,12 +995,12 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(startingToWake())
// WHEN the alternateBouncer stops showing
- bouncerRepository.setPrimaryVisible(false)
+ bouncerRepository.setPrimaryShow(false)
runCurrent()
val info =
withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture())
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
}
// THEN a transition to LOCKSCREEN should occur
assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -1006,6 +1011,92 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
coroutineContext.cancelChildren()
}
+ @Test
+ fun `OCCLUDED to GONE`() =
+ testScope.runTest {
+ // GIVEN a device on lockscreen
+ keyguardRepository.setKeyguardShowing(true)
+ runCurrent()
+
+ // GIVEN a prior transition has run to OCCLUDED
+ runner.startTransition(
+ testScope,
+ TransitionInfo(
+ ownerName = "",
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.OCCLUDED,
+ animator =
+ ValueAnimator().apply {
+ duration = 10
+ interpolator = Interpolators.LINEAR
+ },
+ )
+ )
+ keyguardRepository.setKeyguardOccluded(true)
+ runCurrent()
+ reset(mockTransitionRepository)
+
+ // WHEN keyguard goes away
+ keyguardRepository.setKeyguardShowing(false)
+ // AND occlusion ends
+ keyguardRepository.setKeyguardOccluded(false)
+ runCurrent()
+
+ val info =
+ withArgCaptor<TransitionInfo> {
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
+ }
+ // THEN a transition to GONE should occur
+ assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
+ assertThat(info.from).isEqualTo(KeyguardState.OCCLUDED)
+ assertThat(info.to).isEqualTo(KeyguardState.GONE)
+ assertThat(info.animator).isNotNull()
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun `OCCLUDED to LOCKSCREEN`() =
+ testScope.runTest {
+ // GIVEN a device on lockscreen
+ keyguardRepository.setKeyguardShowing(true)
+ runCurrent()
+
+ // GIVEN a prior transition has run to OCCLUDED
+ runner.startTransition(
+ testScope,
+ TransitionInfo(
+ ownerName = "",
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.OCCLUDED,
+ animator =
+ ValueAnimator().apply {
+ duration = 10
+ interpolator = Interpolators.LINEAR
+ },
+ )
+ )
+ keyguardRepository.setKeyguardOccluded(true)
+ runCurrent()
+ reset(mockTransitionRepository)
+
+ // WHEN occlusion ends
+ keyguardRepository.setKeyguardOccluded(false)
+ runCurrent()
+
+ val info =
+ withArgCaptor<TransitionInfo> {
+ verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
+ }
+ // THEN a transition to LOCKSCREEN should occur
+ assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
+ assertThat(info.from).isEqualTo(KeyguardState.OCCLUDED)
+ assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN)
+ assertThat(info.animator).isNotNull()
+
+ coroutineContext.cancelChildren()
+ }
+
private fun startingToWake() =
WakefulnessModel(
WakefulnessState.STARTING_TO_WAKE,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
index 46ed829e0574..5ec6283f3de0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -19,11 +19,13 @@ package com.android.systemui.keyguard.domain.interactor
import android.os.Looper
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
+import android.testing.TestableResources
import android.view.View
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.DejankUtils
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.keyguard.DismissCallbackRegistry
@@ -33,7 +35,6 @@ import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -69,6 +70,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private val mainHandler = FakeHandler(Looper.getMainLooper())
private lateinit var underTest: PrimaryBouncerInteractor
+ private lateinit var resources: TestableResources
@Before
fun setUp() {
@@ -84,28 +86,27 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
mPrimaryBouncerCallbackInteractor,
falsingCollector,
dismissCallbackRegistry,
- keyguardBypassController,
+ context,
keyguardUpdateMonitor,
+ keyguardBypassController,
)
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
- `when`(repository.primaryBouncerShow.value).thenReturn(null)
+ `when`(repository.primaryBouncerShow.value).thenReturn(false)
`when`(bouncerView.delegate).thenReturn(bouncerViewDelegate)
+ resources = context.orCreateTestableResources
}
@Test
fun testShow_isScrimmed() {
underTest.show(true)
- verify(repository).setOnScreenTurnedOff(false)
verify(repository).setKeyguardAuthenticated(null)
- verify(repository).setPrimaryHide(false)
verify(repository).setPrimaryStartingToHide(false)
verify(repository).setPrimaryScrimmed(true)
verify(repository).setPanelExpansion(EXPANSION_VISIBLE)
verify(repository).setPrimaryShowingSoon(true)
verify(keyguardStateController).notifyPrimaryBouncerShowing(true)
verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToShow()
- verify(repository).setPrimaryVisible(true)
- verify(repository).setPrimaryShow(any(KeyguardBouncerModel::class.java))
+ verify(repository).setPrimaryShow(true)
verify(repository).setPrimaryShowingSoon(false)
verify(mPrimaryBouncerCallbackInteractor).dispatchVisibilityChanged(View.VISIBLE)
}
@@ -128,9 +129,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
verify(falsingCollector).onBouncerHidden()
verify(keyguardStateController).notifyPrimaryBouncerShowing(false)
verify(repository).setPrimaryShowingSoon(false)
- verify(repository).setPrimaryVisible(false)
- verify(repository).setPrimaryHide(true)
- verify(repository).setPrimaryShow(null)
+ verify(repository).setPrimaryShow(false)
verify(mPrimaryBouncerCallbackInteractor).dispatchVisibilityChanged(View.INVISIBLE)
}
@@ -156,9 +155,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
`when`(repository.panelExpansionAmount.value).thenReturn(0.5f)
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
underTest.setPanelExpansion(EXPANSION_HIDDEN)
- verify(repository).setPrimaryVisible(false)
- verify(repository).setPrimaryShow(null)
- verify(repository).setPrimaryHide(true)
+ verify(repository).setPrimaryShow(false)
verify(falsingCollector).onBouncerHidden()
verify(mPrimaryBouncerCallbackInteractor).dispatchReset()
verify(mPrimaryBouncerCallbackInteractor).dispatchFullyHidden()
@@ -207,12 +204,6 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
}
@Test
- fun testOnScreenTurnedOff() {
- underTest.onScreenTurnedOff()
- verify(repository).setOnScreenTurnedOff(true)
- }
-
- @Test
fun testSetKeyguardPosition() {
underTest.setKeyguardPosition(0f)
verify(repository).setKeyguardPosition(0f)
@@ -245,11 +236,11 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Test
fun testIsFullShowing() {
- `when`(repository.primaryBouncerVisible.value).thenReturn(true)
+ `when`(repository.primaryBouncerShow.value).thenReturn(true)
`when`(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE)
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
assertThat(underTest.isFullyShowing()).isTrue()
- `when`(repository.primaryBouncerVisible.value).thenReturn(false)
+ `when`(repository.primaryBouncerShow.value).thenReturn(false)
assertThat(underTest.isFullyShowing()).isFalse()
}
@@ -286,4 +277,98 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
`when`(bouncerViewDelegate.willDismissWithActions()).thenReturn(false)
assertThat(underTest.willDismissWithAction()).isFalse()
}
+
+ @Test
+ fun testSideFpsVisibility() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(true)
+ }
+
+ @Test
+ fun testSideFpsVisibility_notVisible() {
+ updateSideFpsVisibilityParameters(
+ isVisible = false,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_sfpsNotEnabled() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = false,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_fpsDetectionNotRunning() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = false,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_UnlockingWithFpNotAllowed() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = false,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_AnimatingAway() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = true
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ private fun updateSideFpsVisibilityParameters(
+ isVisible: Boolean,
+ sfpsEnabled: Boolean,
+ fpsDetectionRunning: Boolean,
+ isUnlockingWithFpAllowed: Boolean,
+ isAnimatingAway: Boolean
+ ) {
+ `when`(repository.primaryBouncerShow.value).thenReturn(isVisible)
+ resources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, sfpsEnabled)
+ `when`(keyguardUpdateMonitor.isFingerprintDetectionRunning).thenReturn(fpsDetectionRunning)
+ `when`(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
+ .thenReturn(isUnlockingWithFpAllowed)
+ `when`(repository.primaryBouncerStartingDisappearAnimation.value)
+ .thenReturn(if (isAnimatingAway) Runnable {} else null)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
index 75b74b0cfe28..edac468e146e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
@@ -26,7 +26,6 @@ import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView
-import com.android.systemui.keyguard.data.BouncerViewDelegate
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -44,7 +43,6 @@ import org.mockito.MockitoAnnotations
class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
private lateinit var repository: FakeKeyguardBouncerRepository
@Mock private lateinit var bouncerView: BouncerView
- @Mock private lateinit var bouncerViewDelegate: BouncerViewDelegate
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
@Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
@@ -69,8 +67,9 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
primaryBouncerCallbackInteractor,
falsingCollector,
dismissCallbackRegistry,
- keyguardBypassController,
+ context,
keyguardUpdateMonitor,
+ keyguardBypassController,
)
}
@@ -78,7 +77,7 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
fun notInteractableWhenExpansionIsBelow90Percent() = runTest {
val isInteractable = collectLastValue(underTest.isInteractable)
- repository.setPrimaryVisible(true)
+ repository.setPrimaryShow(true)
repository.setPanelExpansion(0.15f)
assertThat(isInteractable()).isFalse()
@@ -88,7 +87,7 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
fun notInteractableWhenExpansionAbove90PercentButNotVisible() = runTest {
val isInteractable = collectLastValue(underTest.isInteractable)
- repository.setPrimaryVisible(false)
+ repository.setPrimaryShow(false)
repository.setPanelExpansion(0.05f)
assertThat(isInteractable()).isFalse()
@@ -98,7 +97,7 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
fun isInteractableWhenExpansionAbove90PercentAndVisible() = runTest {
var isInteractable = collectLastValue(underTest.isInteractable)
- repository.setPrimaryVisible(true)
+ repository.setPrimaryShow(true)
repository.setPanelExpansion(0.09f)
assertThat(isInteractable()).isTrue()
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 8bd8be565eee..c727b3a6cd10 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
@@ -308,7 +308,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
TestConfig(
isVisible = true,
isClickable = false,
- isActivated = true,
+ isActivated = false,
icon = icon,
canShowWhileLocked = false,
intent = Intent("action"),
@@ -363,7 +363,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
TestConfig(
isVisible = true,
isClickable = false,
- isActivated = true,
+ isActivated = false,
icon = icon,
canShowWhileLocked = false,
intent = Intent("action"),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
index 586af626d29e..e66be08426a5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
@@ -16,15 +16,23 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.os.Looper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.utils.os.FakeHandler
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.test.runCurrent
@@ -33,7 +41,6 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito
import org.mockito.MockitoAnnotations
@SmallTest
@@ -41,31 +48,69 @@ import org.mockito.MockitoAnnotations
@kotlinx.coroutines.ExperimentalCoroutinesApi
class KeyguardBouncerViewModelTest : SysuiTestCase() {
lateinit var underTest: KeyguardBouncerViewModel
+ lateinit var bouncerInteractor: PrimaryBouncerInteractor
@Mock lateinit var bouncerView: BouncerView
- @Mock lateinit var bouncerInteractor: PrimaryBouncerInteractor
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
+ @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
+ @Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
+ @Mock private lateinit var falsingCollector: FalsingCollector
+ @Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
+ @Mock private lateinit var keyguardBypassController: KeyguardBypassController
+ @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ private val mainHandler = FakeHandler(Looper.getMainLooper())
+ val repository = FakeKeyguardBouncerRepository()
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
+ bouncerInteractor =
+ PrimaryBouncerInteractor(
+ repository,
+ bouncerView,
+ mainHandler,
+ keyguardStateController,
+ keyguardSecurityModel,
+ primaryBouncerCallbackInteractor,
+ falsingCollector,
+ dismissCallbackRegistry,
+ context,
+ keyguardUpdateMonitor,
+ keyguardBypassController,
+ )
underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor)
}
@Test
- fun setMessage() =
- runTest {
- val flow = MutableStateFlow<BouncerShowMessageModel?>(null)
- var message: BouncerShowMessageModel? = null
- Mockito.`when`(bouncerInteractor.showMessage)
- .thenReturn(flow as Flow<BouncerShowMessageModel>)
- // Reinitialize the view model.
- underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor)
+ fun setMessage() = runTest {
+ var message: BouncerShowMessageModel? = null
+ val job = underTest.bouncerShowMessage.onEach { message = it }.launchIn(this)
- flow.value = BouncerShowMessageModel(message = "abc", colorStateList = null)
+ repository.setShowMessage(BouncerShowMessageModel("abc", null))
+ // Run the tasks that are pending at this point of virtual time.
+ runCurrent()
+ assertThat(message?.message).isEqualTo("abc")
+ job.cancel()
+ }
+
+ @Test
+ fun shouldUpdateSideFps() = runTest {
+ var count = 0
+ val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this)
+ repository.setPrimaryShow(true)
+ // Run the tasks that are pending at this point of virtual time.
+ runCurrent()
+ assertThat(count).isEqualTo(1)
+ job.cancel()
+ }
- val job = underTest.bouncerShowMessage.onEach { message = it }.launchIn(this)
- // Run the tasks that are pending at this point of virtual time.
- runCurrent()
- assertThat(message?.message).isEqualTo("abc")
- job.cancel()
- }
+ @Test
+ fun sideFpsShowing() = runTest {
+ var sideFpsIsShowing = false
+ val job = underTest.sideFpsShowing.onEach { sideFpsIsShowing = it }.launchIn(this)
+ repository.setSideFpsShowing(true)
+ // Run the tasks that are pending at this point of virtual time.
+ runCurrent()
+ assertThat(sideFpsIsShowing).isEqualTo(true)
+ job.cancel()
+ }
}
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
new file mode 100644
index 000000000000..746f66881a88
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
@@ -0,0 +1,180 @@
+/*
+ * 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.keyguard.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.ScrimAlpha
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.util.mockito.whenever
+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.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() {
+ private lateinit var underTest: PrimaryBouncerToGoneTransitionViewModel
+ private lateinit var repository: FakeKeyguardTransitionRepository
+ @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
+ @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ repository = FakeKeyguardTransitionRepository()
+ val interactor = KeyguardTransitionInteractor(repository)
+ underTest =
+ PrimaryBouncerToGoneTransitionViewModel(
+ interactor,
+ statusBarStateController,
+ primaryBouncerInteractor
+ )
+
+ whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(false)
+ whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false)
+ }
+
+ @Test
+ fun bouncerAlpha() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<Float>()
+
+ val job = underTest.bouncerAlpha.onEach { values.add(it) }.launchIn(this)
+
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(0.6f))
+
+ assertThat(values.size).isEqualTo(3)
+ values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
+
+ job.cancel()
+ }
+
+ @Test
+ fun bouncerAlpha_runDimissFromKeyguard() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<Float>()
+
+ val job = underTest.bouncerAlpha.onEach { values.add(it) }.launchIn(this)
+
+ whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(true)
+
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(0.6f))
+
+ assertThat(values.size).isEqualTo(3)
+ values.forEach { assertThat(it).isEqualTo(0f) }
+
+ job.cancel()
+ }
+
+ @Test
+ fun scrimAlpha_runDimissFromKeyguard() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<ScrimAlpha>()
+
+ val job = underTest.scrimAlpha.onEach { values.add(it) }.launchIn(this)
+
+ whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(true)
+
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(0.6f))
+ repository.sendTransitionStep(step(1f))
+
+ assertThat(values.size).isEqualTo(4)
+ values.forEach { assertThat(it).isEqualTo(ScrimAlpha(notificationsAlpha = 1f)) }
+
+ job.cancel()
+ }
+
+ @Test
+ fun scrimBehindAlpha_leaveShadeOpen() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<ScrimAlpha>()
+
+ val job = underTest.scrimAlpha.onEach { values.add(it) }.launchIn(this)
+
+ whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(true)
+
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(0.6f))
+ repository.sendTransitionStep(step(1f))
+
+ assertThat(values.size).isEqualTo(4)
+ values.forEach {
+ assertThat(it).isEqualTo(ScrimAlpha(notificationsAlpha = 1f, behindAlpha = 1f))
+ }
+
+ job.cancel()
+ }
+
+ @Test
+ fun scrimBehindAlpha_doNotLeaveShadeOpen() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<ScrimAlpha>()
+
+ val job = underTest.scrimAlpha.onEach { values.add(it) }.launchIn(this)
+
+ whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false)
+
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(0.6f))
+ repository.sendTransitionStep(step(1f))
+
+ assertThat(values.size).isEqualTo(4)
+ values.forEach { assertThat(it.notificationsAlpha).isEqualTo(0f) }
+ values.forEach { assertThat(it.frontAlpha).isEqualTo(0f) }
+ values.forEach { assertThat(it.behindAlpha).isIn(Range.closed(0f, 1f)) }
+ assertThat(values[3].behindAlpha).isEqualTo(0f)
+
+ job.cancel()
+ }
+
+ private fun step(
+ value: Float,
+ state: TransitionState = TransitionState.RUNNING
+ ): TransitionStep {
+ return TransitionStep(
+ from = KeyguardState.PRIMARY_BOUNCER,
+ to = KeyguardState.GONE,
+ value = value,
+ transitionState = state,
+ ownerName = "PrimaryBouncerToGoneTransitionViewModelTest"
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt
index c7f3fa0830cd..fb20bacee64c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt
@@ -121,4 +121,92 @@ class TableChangeTest : SysuiTestCase() {
assertThat(underTest.getName()).doesNotContain("original")
assertThat(underTest.getVal()).isEqualTo("8900")
}
+
+ @Test
+ fun updateTo_emptyToString_isString() {
+ val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+
+ val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+ new.set("newString")
+ underTest.updateTo(new)
+
+ assertThat(underTest.hasData()).isTrue()
+ assertThat(underTest.getName()).contains("newPrefix")
+ assertThat(underTest.getName()).contains("newName")
+ assertThat(underTest.getVal()).isEqualTo("newString")
+ }
+
+ @Test
+ fun updateTo_intToEmpty_isEmpty() {
+ val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+ underTest.set(42)
+
+ val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+ underTest.updateTo(new)
+
+ assertThat(underTest.hasData()).isFalse()
+ assertThat(underTest.getName()).contains("newPrefix")
+ assertThat(underTest.getName()).contains("newName")
+ assertThat(underTest.getVal()).isEqualTo("null")
+ }
+
+ @Test
+ fun updateTo_stringToBool_isBool() {
+ val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+ underTest.set("oldString")
+
+ val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+ new.set(true)
+ underTest.updateTo(new)
+
+ assertThat(underTest.hasData()).isTrue()
+ assertThat(underTest.getName()).contains("newPrefix")
+ assertThat(underTest.getName()).contains("newName")
+ assertThat(underTest.getVal()).isEqualTo("true")
+ }
+
+ @Test
+ fun updateTo_intToString_isString() {
+ val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+ underTest.set(43)
+
+ val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+ new.set("newString")
+ underTest.updateTo(new)
+
+ assertThat(underTest.hasData()).isTrue()
+ assertThat(underTest.getName()).contains("newPrefix")
+ assertThat(underTest.getName()).contains("newName")
+ assertThat(underTest.getVal()).isEqualTo("newString")
+ }
+
+ @Test
+ fun updateTo_boolToInt_isInt() {
+ val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+ underTest.set(false)
+
+ val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+ new.set(44)
+ underTest.updateTo(new)
+
+ assertThat(underTest.hasData()).isTrue()
+ assertThat(underTest.getName()).contains("newPrefix")
+ assertThat(underTest.getName()).contains("newName")
+ assertThat(underTest.getVal()).isEqualTo("44")
+ }
+
+ @Test
+ fun updateTo_boolToNewBool_isNewBool() {
+ val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+ underTest.set(false)
+
+ val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+ new.set(true)
+ underTest.updateTo(new)
+
+ assertThat(underTest.hasData()).isTrue()
+ assertThat(underTest.getName()).contains("newPrefix")
+ assertThat(underTest.getName()).contains("newName")
+ assertThat(underTest.getVal()).isEqualTo("true")
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
index 2c8d7abd4f4a..949fa1cce0cb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
@@ -435,11 +435,236 @@ class TableLogBufferTest : SysuiTestCase() {
assertThat(dumpedString).doesNotContain("testString[0]")
assertThat(dumpedString).doesNotContain("testString[1]")
- assertThat(dumpedString).doesNotContain("testString[2]")
+ // The buffer should contain [MAX_SIZE + 1] entries since we also save the most recently
+ // evicted value.
+ assertThat(dumpedString).contains("testString[2]")
assertThat(dumpedString).contains("testString[3]")
assertThat(dumpedString).contains("testString[${MAX_SIZE + 2}]")
}
+ @Test
+ fun columnEvicted_lastKnownColumnValueInDump() {
+ systemClock.setCurrentTimeMillis(100L)
+ underTest.logChange(prefix = "", columnName = "willBeEvicted", value = "evictedValue")
+
+ // Exactly fill the buffer so that "willBeEvicted" is evicted
+ for (i in 0 until MAX_SIZE) {
+ systemClock.advanceTime(100L)
+ val dumpString = "fillString[$i]"
+ underTest.logChange(prefix = "", columnName = "fillingColumn", value = dumpString)
+ }
+
+ val dumpedString = dumpChanges()
+
+ // Expect that we'll have both the evicted column entry...
+ val evictedColumnLog =
+ TABLE_LOG_DATE_FORMAT.format(100L) +
+ SEPARATOR +
+ "willBeEvicted" +
+ SEPARATOR +
+ "evictedValue"
+ assertThat(dumpedString).contains(evictedColumnLog)
+
+ // ... *and* all of the fillingColumn entries.
+ val firstFillingColumnLog =
+ TABLE_LOG_DATE_FORMAT.format(200L) +
+ SEPARATOR +
+ "fillingColumn" +
+ SEPARATOR +
+ "fillString[0]"
+ val lastFillingColumnLog =
+ TABLE_LOG_DATE_FORMAT.format(1100L) +
+ SEPARATOR +
+ "fillingColumn" +
+ SEPARATOR +
+ "fillString[9]"
+ assertThat(dumpedString).contains(firstFillingColumnLog)
+ assertThat(dumpedString).contains(lastFillingColumnLog)
+ }
+
+ @Test
+ fun multipleColumnsEvicted_allColumnsInDump() {
+ systemClock.setCurrentTimeMillis(100L)
+ underTest.logChange(prefix = "", columnName = "willBeEvictedString", value = "evictedValue")
+ systemClock.advanceTime(100L)
+ underTest.logChange(prefix = "", columnName = "willBeEvictedInt", value = 45)
+ systemClock.advanceTime(100L)
+ underTest.logChange(prefix = "", columnName = "willBeEvictedBool", value = true)
+
+ // Exactly fill the buffer so that all the above columns will be evicted
+ for (i in 0 until MAX_SIZE) {
+ systemClock.advanceTime(100L)
+ val dumpString = "fillString[$i]"
+ underTest.logChange(prefix = "", columnName = "fillingColumn", value = dumpString)
+ }
+
+ val dumpedString = dumpChanges()
+
+ // Expect that we'll have all the evicted column entries...
+ val evictedColumnLogString =
+ TABLE_LOG_DATE_FORMAT.format(100L) +
+ SEPARATOR +
+ "willBeEvictedString" +
+ SEPARATOR +
+ "evictedValue"
+ val evictedColumnLogInt =
+ TABLE_LOG_DATE_FORMAT.format(200L) + SEPARATOR + "willBeEvictedInt" + SEPARATOR + "45"
+ val evictedColumnLogBool =
+ TABLE_LOG_DATE_FORMAT.format(300L) +
+ SEPARATOR +
+ "willBeEvictedBool" +
+ SEPARATOR +
+ "true"
+ assertThat(dumpedString).contains(evictedColumnLogString)
+ assertThat(dumpedString).contains(evictedColumnLogInt)
+ assertThat(dumpedString).contains(evictedColumnLogBool)
+
+ // ... *and* all of the fillingColumn entries.
+ val firstFillingColumnLog =
+ TABLE_LOG_DATE_FORMAT.format(400) +
+ SEPARATOR +
+ "fillingColumn" +
+ SEPARATOR +
+ "fillString[0]"
+ val lastFillingColumnLog =
+ TABLE_LOG_DATE_FORMAT.format(1300) +
+ SEPARATOR +
+ "fillingColumn" +
+ SEPARATOR +
+ "fillString[9]"
+ assertThat(dumpedString).contains(firstFillingColumnLog)
+ assertThat(dumpedString).contains(lastFillingColumnLog)
+ }
+
+ @Test
+ fun multipleColumnsEvicted_differentPrefixSameName_allColumnsInDump() {
+ systemClock.setCurrentTimeMillis(100L)
+ underTest.logChange(prefix = "prefix1", columnName = "sameName", value = "value1")
+ systemClock.advanceTime(100L)
+ underTest.logChange(prefix = "prefix2", columnName = "sameName", value = "value2")
+ systemClock.advanceTime(100L)
+ underTest.logChange(prefix = "prefix3", columnName = "sameName", value = "value3")
+
+ // Exactly fill the buffer so that all the above columns will be evicted
+ for (i in 0 until MAX_SIZE) {
+ systemClock.advanceTime(100L)
+ val dumpString = "fillString[$i]"
+ underTest.logChange(prefix = "", columnName = "fillingColumn", value = dumpString)
+ }
+
+ val dumpedString = dumpChanges()
+
+ // Expect that we'll have all the evicted column entries
+ val evictedColumn1 =
+ TABLE_LOG_DATE_FORMAT.format(100L) +
+ SEPARATOR +
+ "prefix1.sameName" +
+ SEPARATOR +
+ "value1"
+ val evictedColumn2 =
+ TABLE_LOG_DATE_FORMAT.format(200L) +
+ SEPARATOR +
+ "prefix2.sameName" +
+ SEPARATOR +
+ "value2"
+ val evictedColumn3 =
+ TABLE_LOG_DATE_FORMAT.format(300L) +
+ SEPARATOR +
+ "prefix3.sameName" +
+ SEPARATOR +
+ "value3"
+ assertThat(dumpedString).contains(evictedColumn1)
+ assertThat(dumpedString).contains(evictedColumn2)
+ assertThat(dumpedString).contains(evictedColumn3)
+ }
+
+ @Test
+ fun multipleColumnsEvicted_dumpSortedByTimestamp() {
+ systemClock.setCurrentTimeMillis(100L)
+ underTest.logChange(prefix = "", columnName = "willBeEvictedFirst", value = "evictedValue")
+ systemClock.advanceTime(100L)
+ underTest.logChange(prefix = "", columnName = "willBeEvictedSecond", value = 45)
+ systemClock.advanceTime(100L)
+ underTest.logChange(prefix = "", columnName = "willBeEvictedThird", value = true)
+
+ // Exactly fill the buffer with so that all the above columns will be evicted
+ for (i in 0 until MAX_SIZE) {
+ systemClock.advanceTime(100L)
+ val dumpString = "fillString[$i]"
+ underTest.logChange(prefix = "", columnName = "fillingColumn", value = dumpString)
+ }
+
+ val dumpedString = dumpChanges()
+
+ // Expect that we'll have all the evicted column entries in timestamp order
+ val firstEvictedLog =
+ TABLE_LOG_DATE_FORMAT.format(100L) +
+ SEPARATOR +
+ "willBeEvictedFirst" +
+ SEPARATOR +
+ "evictedValue"
+ val secondEvictedLog =
+ TABLE_LOG_DATE_FORMAT.format(200L) +
+ SEPARATOR +
+ "willBeEvictedSecond" +
+ SEPARATOR +
+ "45"
+ val thirdEvictedLog =
+ TABLE_LOG_DATE_FORMAT.format(300L) +
+ SEPARATOR +
+ "willBeEvictedThird" +
+ SEPARATOR +
+ "true"
+ assertThat(dumpedString).contains(firstEvictedLog)
+ val stringAfterFirst = dumpedString.substringAfter(firstEvictedLog)
+ assertThat(stringAfterFirst).contains(secondEvictedLog)
+ val stringAfterSecond = stringAfterFirst.substringAfter(secondEvictedLog)
+ assertThat(stringAfterSecond).contains(thirdEvictedLog)
+ }
+
+ @Test
+ fun sameColumnEvictedMultipleTimes_onlyLastEvictionInDump() {
+ systemClock.setCurrentTimeMillis(0L)
+
+ for (i in 1 until 4) {
+ systemClock.advanceTime(100L)
+ val dumpString = "evicted[$i]"
+ underTest.logChange(prefix = "", columnName = "evictedColumn", value = dumpString)
+ }
+
+ // Exactly fill the buffer so that all the entries for "evictedColumn" will be evicted.
+ for (i in 0 until MAX_SIZE) {
+ systemClock.advanceTime(100L)
+ val dumpString = "fillString[$i]"
+ underTest.logChange(prefix = "", columnName = "fillingColumn", value = dumpString)
+ }
+
+ val dumpedString = dumpChanges()
+
+ // Expect that we only have the most recent evicted column entry
+ val evictedColumnLog1 =
+ TABLE_LOG_DATE_FORMAT.format(100L) +
+ SEPARATOR +
+ "evictedColumn" +
+ SEPARATOR +
+ "evicted[1]"
+ val evictedColumnLog2 =
+ TABLE_LOG_DATE_FORMAT.format(200L) +
+ SEPARATOR +
+ "evictedColumn" +
+ SEPARATOR +
+ "evicted[2]"
+ val evictedColumnLog3 =
+ TABLE_LOG_DATE_FORMAT.format(300L) +
+ SEPARATOR +
+ "evictedColumn" +
+ SEPARATOR +
+ "evicted[3]"
+ assertThat(dumpedString).doesNotContain(evictedColumnLog1)
+ assertThat(dumpedString).doesNotContain(evictedColumnLog2)
+ assertThat(dumpedString).contains(evictedColumnLog3)
+ }
+
private fun dumpChanges(): String {
underTest.dump(PrintWriter(outputWriter), arrayOf())
return outputWriter.toString()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
index eb6235ca8a6a..8532ffed85fb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.media.controls.pipeline
import android.app.smartspace.SmartspaceAction
+import android.os.Bundle
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
@@ -25,6 +26,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.media.controls.MediaTestUtils
import com.android.systemui.media.controls.models.player.MediaData
+import com.android.systemui.media.controls.models.recommendation.EXTRA_KEY_TRIGGER_RESUME
import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
import com.android.systemui.media.controls.ui.MediaPlayerData
import com.android.systemui.media.controls.util.MediaFlags
@@ -75,6 +77,7 @@ class MediaDataFilterTest : SysuiTestCase() {
@Mock private lateinit var smartspaceMediaRecommendationItem: SmartspaceAction
@Mock private lateinit var logger: MediaUiEventLogger
@Mock private lateinit var mediaFlags: MediaFlags
+ @Mock private lateinit var cardAction: SmartspaceAction
private lateinit var mediaDataFilter: MediaDataFilter
private lateinit var dataMain: MediaData
@@ -122,6 +125,7 @@ class MediaDataFilterTest : SysuiTestCase() {
whenever(smartspaceData.headphoneConnectionTimeMillis)
.thenReturn(clock.currentTimeMillis() - 100)
whenever(smartspaceData.instanceId).thenReturn(SMARTSPACE_INSTANCE_ID)
+ whenever(smartspaceData.cardAction).thenReturn(cardAction)
}
private fun setUser(id: Int) {
@@ -574,4 +578,55 @@ class MediaDataFilterTest : SysuiTestCase() {
verify(mediaDataManager, never())
.dismissSmartspaceRecommendation(eq(SMARTSPACE_KEY), anyLong())
}
+
+ @Test
+ fun testSmartspaceLoaded_shouldTriggerResume_doesTrigger() {
+ // WHEN we have media that was recently played, but not currently active
+ val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
+ mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
+ verify(listener)
+ .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
+
+ // AND we get a smartspace signal with extra to trigger resume
+ val extras = Bundle().apply { putBoolean(EXTRA_KEY_TRIGGER_RESUME, true) }
+ whenever(cardAction.extras).thenReturn(extras)
+ mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+
+ // THEN we should tell listeners to treat the media as active instead
+ val dataCurrentAndActive = dataCurrent.copy(active = true)
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(KEY),
+ eq(KEY),
+ eq(dataCurrentAndActive),
+ eq(true),
+ eq(100),
+ eq(true)
+ )
+ assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue()
+ // And send the smartspace data, but not prioritized
+ verify(listener)
+ .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
+ }
+
+ @Test
+ fun testSmartspaceLoaded_notShouldTriggerResume_doesNotTrigger() {
+ // WHEN we have media that was recently played, but not currently active
+ val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
+ mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
+ verify(listener)
+ .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
+
+ // AND we get a smartspace signal with extra to not trigger resume
+ val extras = Bundle().apply { putBoolean(EXTRA_KEY_TRIGGER_RESUME, false) }
+ whenever(cardAction.extras).thenReturn(extras)
+ mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+
+ // THEN listeners are not updated to show media
+ verify(listener, never())
+ .onMediaDataLoaded(eq(KEY), eq(KEY), any(), eq(true), eq(100), eq(true))
+ // But the smartspace update is still propagated
+ verify(listener)
+ .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
index a07a714ebc77..d428db7b9dda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
@@ -93,6 +93,8 @@ private const val SYSTEM_PACKAGE_NAME = "com.android.systemui"
private const val APP_NAME = "SystemUI"
private const val SESSION_ARTIST = "artist"
private const val SESSION_TITLE = "title"
+private const val SESSION_BLANK_TITLE = " "
+private const val SESSION_EMPTY_TITLE = ""
private const val USER_ID = 0
private val DISMISS_INTENT = Intent().apply { action = "dismiss" }
@@ -137,6 +139,7 @@ class MediaDataManagerTest : SysuiTestCase() {
@Mock private lateinit var logger: MediaUiEventLogger
lateinit var mediaDataManager: MediaDataManager
lateinit var mediaNotification: StatusBarNotification
+ lateinit var remoteCastNotification: StatusBarNotification
@Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
private val clock = FakeSystemClock()
@Mock private lateinit var tunerService: TunerService
@@ -205,6 +208,20 @@ class MediaDataManagerTest : SysuiTestCase() {
}
build()
}
+ remoteCastNotification =
+ SbnBuilder().run {
+ setPkg(SYSTEM_PACKAGE_NAME)
+ modifyNotification(context).also {
+ it.setSmallIcon(android.R.drawable.ic_media_pause)
+ it.setStyle(
+ MediaStyle().apply {
+ setMediaSession(session.sessionToken)
+ setRemotePlaybackInfo("Remote device", 0, null)
+ }
+ )
+ }
+ build()
+ }
metadataBuilder =
MediaMetadata.Builder().apply {
putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
@@ -214,6 +231,7 @@ class MediaDataManagerTest : SysuiTestCase() {
whenever(mediaControllerFactory.create(eq(session.sessionToken))).thenReturn(controller)
whenever(controller.transportControls).thenReturn(transportControls)
whenever(controller.playbackInfo).thenReturn(playbackInfo)
+ whenever(controller.metadata).thenReturn(metadataBuilder.build())
whenever(playbackInfo.playbackType)
.thenReturn(MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL)
@@ -244,6 +262,7 @@ class MediaDataManagerTest : SysuiTestCase() {
whenever(mediaFlags.isExplicitIndicatorEnabled()).thenReturn(true)
whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(false)
whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(false)
whenever(logger.getNewInstanceId()).thenReturn(instanceIdSequence.newInstanceId())
whenever(keyguardUpdateMonitor.isUserInLockdown(any())).thenReturn(false)
}
@@ -318,18 +337,15 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testLoadMetadata_withExplicitIndicator() {
- val metadata =
- MediaMetadata.Builder().run {
- putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
- putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
- putLong(
- MediaConstants.METADATA_KEY_IS_EXPLICIT,
- MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT
- )
- build()
- }
- whenever(mediaControllerFactory.create(anyObject())).thenReturn(controller)
- whenever(controller.metadata).thenReturn(metadata)
+ whenever(controller.metadata)
+ .thenReturn(
+ metadataBuilder
+ .putLong(
+ MediaConstants.METADATA_KEY_IS_EXPLICIT,
+ MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT
+ )
+ .build()
+ )
mediaDataManager.addListener(listener)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
@@ -350,9 +366,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnMetaDataLoaded_withoutExplicitIndicator() {
- whenever(mediaControllerFactory.create(anyObject())).thenReturn(controller)
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
-
mediaDataManager.addListener(listener)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
@@ -385,7 +398,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnMetaDataLoaded_conservesActiveFlag() {
whenever(mediaControllerFactory.create(anyObject())).thenReturn(controller)
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
mediaDataManager.addListener(listener)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
@@ -404,33 +416,8 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnNotificationAdded_isRcn_markedRemote() {
- val rcn =
- SbnBuilder().run {
- setPkg(SYSTEM_PACKAGE_NAME)
- modifyNotification(context).also {
- it.setSmallIcon(android.R.drawable.ic_media_pause)
- it.setStyle(
- MediaStyle().apply {
- setMediaSession(session.sessionToken)
- setRemotePlaybackInfo("Remote device", 0, null)
- }
- )
- }
- build()
- }
+ addNotificationAndLoad(remoteCastNotification)
- mediaDataManager.onNotificationAdded(KEY, rcn)
- assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
- assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
- verify(listener)
- .onMediaDataLoaded(
- eq(KEY),
- eq(null),
- capture(mediaDataCaptor),
- eq(true),
- eq(0),
- eq(false)
- )
assertThat(mediaDataCaptor.value!!.playbackLocation)
.isEqualTo(MediaData.PLAYBACK_CAST_REMOTE)
verify(logger)
@@ -530,9 +517,78 @@ class MediaDataManagerTest : SysuiTestCase() {
}
@Test
+ fun testOnNotificationRemoved_emptyTitle_notConverted() {
+ // GIVEN that the manager has a notification with a resume action and empty title.
+ whenever(controller.metadata)
+ .thenReturn(
+ metadataBuilder
+ .putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_EMPTY_TITLE)
+ .build()
+ )
+ addNotificationAndLoad()
+ val data = mediaDataCaptor.value
+ val instanceId = data.instanceId
+ assertThat(data.resumption).isFalse()
+ mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
+
+ // WHEN the notification is removed
+ reset(listener)
+ mediaDataManager.onNotificationRemoved(KEY)
+
+ // THEN active media is not converted to resume.
+ verify(listener, never())
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ verify(logger, never())
+ .logActiveConvertedToResume(anyInt(), eq(PACKAGE_NAME), eq(instanceId))
+ verify(logger, never()).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), any())
+ verify(logger).logMediaRemoved(anyInt(), eq(PACKAGE_NAME), eq(instanceId))
+ }
+
+ @Test
+ fun testOnNotificationRemoved_blankTitle_notConverted() {
+ // GIVEN that the manager has a notification with a resume action and blank title.
+ whenever(controller.metadata)
+ .thenReturn(
+ metadataBuilder
+ .putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_BLANK_TITLE)
+ .build()
+ )
+ addNotificationAndLoad()
+ val data = mediaDataCaptor.value
+ val instanceId = data.instanceId
+ assertThat(data.resumption).isFalse()
+ mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
+
+ // WHEN the notification is removed
+ reset(listener)
+ mediaDataManager.onNotificationRemoved(KEY)
+
+ // THEN active media is not converted to resume.
+ verify(listener, never())
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ verify(logger, never())
+ .logActiveConvertedToResume(anyInt(), eq(PACKAGE_NAME), eq(instanceId))
+ verify(logger, never()).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), any())
+ verify(logger).logMediaRemoved(anyInt(), eq(PACKAGE_NAME), eq(instanceId))
+ }
+
+ @Test
fun testOnNotificationRemoved_withResumption() {
// GIVEN that the manager has a notification with a resume action
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
addNotificationAndLoad()
val data = mediaDataCaptor.value
assertThat(data.resumption).isFalse()
@@ -557,7 +613,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnNotificationRemoved_twoWithResumption() {
// GIVEN that the manager has two notifications with resume actions
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
mediaDataManager.onNotificationAdded(KEY_2, mediaNotification)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(2)
@@ -623,7 +678,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnNotificationRemoved_withResumption_butNotLocal() {
// GIVEN that the manager has a notification with a resume action, but is not local
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
whenever(playbackInfo.playbackType)
.thenReturn(MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE)
addNotificationAndLoad()
@@ -647,6 +701,56 @@ class MediaDataManagerTest : SysuiTestCase() {
}
@Test
+ fun testOnNotificationRemoved_withResumption_isRemoteAndRemoteAllowed() {
+ // With the flag enabled to allow remote media to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // GIVEN that the manager has a notification with a resume action, but is not local
+ whenever(controller.metadata).thenReturn(metadataBuilder.build())
+ whenever(playbackInfo.playbackType)
+ .thenReturn(MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE)
+ addNotificationAndLoad()
+ val data = mediaDataCaptor.value
+ val dataRemoteWithResume =
+ data.copy(resumeAction = Runnable {}, playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
+ mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume)
+
+ // WHEN the notification is removed
+ mediaDataManager.onNotificationRemoved(KEY)
+
+ // THEN the media data is converted to a resume state
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ assertThat(mediaDataCaptor.value.resumption).isTrue()
+ }
+
+ @Test
+ fun testOnNotificationRemoved_withResumption_isRcnAndRemoteAllowed() {
+ // With the flag enabled to allow remote media to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // GIVEN that the manager has a remote cast notification
+ addNotificationAndLoad(remoteCastNotification)
+ val data = mediaDataCaptor.value
+ assertThat(data.playbackLocation).isEqualTo(MediaData.PLAYBACK_CAST_REMOTE)
+ val dataRemoteWithResume = data.copy(resumeAction = Runnable {})
+ mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume)
+
+ // WHEN the RCN is removed
+ mediaDataManager.onNotificationRemoved(KEY)
+
+ // THEN the media data is removed
+ verify(listener).onMediaDataRemoved(eq(KEY))
+ }
+
+ @Test
fun testOnNotificationRemoved_withResumption_tooManyPlayers() {
// Given the maximum number of resume controls already
val desc =
@@ -660,7 +764,6 @@ class MediaDataManagerTest : SysuiTestCase() {
}
// And an active, resumable notification
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
addNotificationAndLoad()
val data = mediaDataCaptor.value
assertThat(data.resumption).isFalse()
@@ -845,6 +948,74 @@ class MediaDataManagerTest : SysuiTestCase() {
}
@Test
+ fun testAddResumptionControls_hasEmptyTitle() {
+ whenever(mediaFlags.isResumeProgressEnabled()).thenReturn(true)
+
+ // WHEN resumption controls are added that have empty title
+ val desc =
+ MediaDescription.Builder().run {
+ setTitle(SESSION_EMPTY_TITLE)
+ build()
+ }
+ mediaDataManager.addResumptionControls(
+ USER_ID,
+ desc,
+ Runnable {},
+ session.sessionToken,
+ APP_NAME,
+ pendingIntent,
+ PACKAGE_NAME
+ )
+
+ // Resumption controls are not added.
+ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(foregroundExecutor.runAllReady()).isEqualTo(0)
+ verify(listener, never())
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(null),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ }
+
+ @Test
+ fun testAddResumptionControls_hasBlankTitle() {
+ whenever(mediaFlags.isResumeProgressEnabled()).thenReturn(true)
+
+ // WHEN resumption controls are added that have a blank title
+ val desc =
+ MediaDescription.Builder().run {
+ setTitle(SESSION_BLANK_TITLE)
+ build()
+ }
+ mediaDataManager.addResumptionControls(
+ USER_ID,
+ desc,
+ Runnable {},
+ session.sessionToken,
+ APP_NAME,
+ pendingIntent,
+ PACKAGE_NAME
+ )
+
+ // Resumption controls are not added.
+ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(foregroundExecutor.runAllReady()).isEqualTo(0)
+ verify(listener, never())
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(null),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ }
+
+ @Test
fun testResumptionDisabled_dismissesResumeControls() {
// WHEN there are resume controls and resumption is switched off
val desc =
@@ -1213,7 +1384,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnActiveMediaConverted_doesNotUpdateLastActiveTime() {
// GIVEN that the manager has a notification with a resume action
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
addNotificationAndLoad()
val data = mediaDataCaptor.value
val instanceId = data.instanceId
@@ -1513,7 +1683,6 @@ class MediaDataManagerTest : SysuiTestCase() {
val instanceId = mediaDataCaptor.value.instanceId
// Location is updated to local cast
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
whenever(playbackInfo.playbackType)
.thenReturn(MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE)
addNotificationAndLoad()
@@ -1526,22 +1695,7 @@ class MediaDataManagerTest : SysuiTestCase() {
)
// update to remote cast
- val rcn =
- SbnBuilder().run {
- setPkg(SYSTEM_PACKAGE_NAME) // System package
- modifyNotification(context).also {
- it.setSmallIcon(android.R.drawable.ic_media_pause)
- it.setStyle(
- MediaStyle().apply {
- setMediaSession(session.sessionToken)
- setRemotePlaybackInfo("Remote device", 0, null)
- }
- )
- }
- build()
- }
-
- mediaDataManager.onNotificationAdded(KEY, rcn)
+ mediaDataManager.onNotificationAdded(KEY, remoteCastNotification)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
verify(logger)
@@ -1589,7 +1743,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testPlaybackStateChange_keyHasNullToken_doesNothing() {
// When we get an update that sets the data's token to null
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
addNotificationAndLoad()
val data = mediaDataCaptor.value
assertThat(data.resumption).isFalse()
@@ -1878,7 +2031,7 @@ class MediaDataManagerTest : SysuiTestCase() {
}
@Test
- fun testRetain_sessionPlayer_destroyedWhileActive_fullyRemoved() {
+ fun testRetain_sessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(true)
whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
addPlaybackStateAction()
@@ -1898,6 +2051,40 @@ class MediaDataManagerTest : SysuiTestCase() {
}
@Test
+ fun testRetain_sessionPlayer_canResume_destroyedWhileActive_setToResume() {
+ whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(true)
+ whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
+ addPlaybackStateAction()
+
+ // When a media control using session actions and that does allow resumption is added,
+ addNotificationAndLoad()
+ val dataResumable = mediaDataCaptor.value.copy(resumeAction = Runnable {})
+ mediaDataManager.onMediaDataLoaded(KEY, null, dataResumable)
+
+ // And then the session is destroyed without timing out first
+ sessionCallbackCaptor.value.invoke(KEY)
+
+ // It is converted to a resume player
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ assertThat(mediaDataCaptor.value.resumption).isTrue()
+ assertThat(mediaDataCaptor.value.active).isFalse()
+ verify(logger)
+ .logActiveConvertedToResume(
+ anyInt(),
+ eq(PACKAGE_NAME),
+ eq(mediaDataCaptor.value.instanceId)
+ )
+ }
+
+ @Test
fun testSessionDestroyed_noNotificationKey_stillRemoved() {
whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(true)
whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
@@ -1911,9 +2098,14 @@ class MediaDataManagerTest : SysuiTestCase() {
verify(listener).onMediaDataRemoved(eq(KEY))
}
- /** Helper function to add a media notification and capture the resulting MediaData */
+ /** Helper function to add a basic media notification and capture the resulting MediaData */
private fun addNotificationAndLoad() {
- mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ addNotificationAndLoad(mediaNotification)
+ }
+
+ /** Helper function to add the given notification and capture the resulting MediaData */
+ private fun addNotificationAndLoad(sbn: StatusBarNotification) {
+ mediaDataManager.onNotificationAdded(KEY, sbn)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
verify(listener)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
index 136ace173795..9ab728949e40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
@@ -38,6 +38,7 @@ import com.android.systemui.media.controls.models.player.MediaData
import com.android.systemui.media.controls.models.player.MediaDeviceData
import com.android.systemui.media.controls.pipeline.MediaDataManager
import com.android.systemui.media.controls.pipeline.RESUME_MEDIA_TIMEOUT
+import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.settings.UserTracker
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.concurrency.FakeExecutor
@@ -92,6 +93,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
@Mock private lateinit var mockContext: Context
@Mock private lateinit var pendingIntent: PendingIntent
@Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var mediaFlags: MediaFlags
@Captor lateinit var callbackCaptor: ArgumentCaptor<ResumeMediaBrowser.Callback>
@Captor lateinit var actionCaptor: ArgumentCaptor<Runnable>
@@ -134,6 +136,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
whenever(mockContext.packageManager).thenReturn(context.packageManager)
whenever(mockContext.contentResolver).thenReturn(context.contentResolver)
whenever(mockContext.userId).thenReturn(context.userId)
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(false)
executor = FakeExecutor(clock)
resumeListener =
@@ -146,7 +149,8 @@ class MediaResumeListenerTest : SysuiTestCase() {
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
@@ -188,7 +192,8 @@ class MediaResumeListenerTest : SysuiTestCase() {
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
listener.setManager(mediaDataManager)
verify(broadcastDispatcher, never())
@@ -244,6 +249,32 @@ class MediaResumeListenerTest : SysuiTestCase() {
}
@Test
+ fun testOnLoad_localCast_remoteResumeAllowed_doesCheck() {
+ // If local cast media is allowed to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // When media data is loaded that has not been checked yet, and is a local cast
+ val dataCast = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
+ resumeListener.onMediaDataLoaded(KEY, null, dataCast)
+
+ // Then we report back to the manager
+ verify(mediaDataManager).setResumeAction(KEY, null)
+ }
+
+ @Test
+ fun testOnLoad_remoteCast_remoteResumeAllowed_doesCheck() {
+ // If local cast media is allowed to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // When media data is loaded that has not been checked yet, and is a remote cast
+ val dataRcn = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_REMOTE)
+ resumeListener.onMediaDataLoaded(KEY, null, dataRcn)
+
+ // Then we do not take action
+ verify(mediaDataManager, never()).setResumeAction(any(), any())
+ }
+
+ @Test
fun testOnLoad_checksForResume_hasService() {
setUpMbsWithValidResolveInfo()
@@ -282,6 +313,25 @@ class MediaResumeListenerTest : SysuiTestCase() {
}
@Test
+ fun testOnLoadTwice_onlyChecksOnce() {
+ // When data is first loaded,
+ setUpMbsWithValidResolveInfo()
+ resumeListener.onMediaDataLoaded(KEY, null, data)
+
+ // We notify the manager to set a null action
+ verify(mediaDataManager).setResumeAction(KEY, null)
+
+ // If we then get another update from the app before the first check completes
+ assertThat(executor.numPending()).isEqualTo(1)
+ var dataWithCheck = data.copy(hasCheckedForResume = true)
+ resumeListener.onMediaDataLoaded(KEY, null, dataWithCheck)
+
+ // We do not try to start another check
+ assertThat(executor.numPending()).isEqualTo(1)
+ verify(mediaDataManager).setResumeAction(KEY, null)
+ }
+
+ @Test
fun testOnUserUnlock_loadsTracks() {
// Set up mock service to successfully find valid media
val description = MediaDescription.Builder().setTitle(TITLE).build()
@@ -361,7 +411,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
assertThat(result.size).isEqualTo(3)
assertThat(result[2].toLong()).isEqualTo(currentTime)
}
- verify(sharedPrefsEditor, times(1)).apply()
+ verify(sharedPrefsEditor).apply()
}
@Test
@@ -389,7 +439,8 @@ class MediaResumeListenerTest : SysuiTestCase() {
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
@@ -400,8 +451,8 @@ class MediaResumeListenerTest : SysuiTestCase() {
resumeListener.userUnlockReceiver.onReceive(mockContext, intent)
// We add its resume controls
- verify(resumeBrowser, times(1)).findRecentMedia()
- verify(mediaDataManager, times(1))
+ verify(resumeBrowser).findRecentMedia()
+ verify(mediaDataManager)
.addResumptionControls(anyInt(), any(), any(), any(), any(), any(), eq(PACKAGE_NAME))
}
@@ -421,7 +472,8 @@ class MediaResumeListenerTest : SysuiTestCase() {
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
@@ -463,7 +515,8 @@ class MediaResumeListenerTest : SysuiTestCase() {
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
@@ -482,7 +535,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
assertThat(result.size).isEqualTo(3)
assertThat(result[2].toLong()).isEqualTo(currentTime)
}
- verify(sharedPrefsEditor, times(1)).apply()
+ verify(sharedPrefsEditor).apply()
}
@Test
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 a72634bcb807..e0ca90ec2c58 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
@@ -17,7 +17,7 @@
package com.android.systemui.media.controls.ui
import android.app.PendingIntent
-import android.content.res.Configuration
+import android.content.res.ColorStateList
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.util.MathUtils.abs
@@ -26,9 +26,9 @@ import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -49,7 +49,7 @@ import com.android.systemui.qs.PageIndicator
import com.android.systemui.statusbar.notification.collection.provider.OnReorderingAllowedListener
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
@@ -89,7 +89,6 @@ class MediaCarouselControllerTest : SysuiTestCase() {
@Mock lateinit var mediaHostStatesManager: MediaHostStatesManager
@Mock lateinit var mediaHostState: MediaHostState
@Mock lateinit var activityStarter: ActivityStarter
- @Mock @Main private lateinit var executor: DelayableExecutor
@Mock lateinit var mediaDataManager: MediaDataManager
@Mock lateinit var configurationController: ConfigurationController
@Mock lateinit var falsingCollector: FalsingCollector
@@ -113,11 +112,15 @@ class MediaCarouselControllerTest : SysuiTestCase() {
private val clock = FakeSystemClock()
private lateinit var mediaCarouselController: MediaCarouselController
+ private lateinit var mainExecutor: FakeExecutor
+ private lateinit var backgroundExecutor: FakeExecutor
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
transitionRepository = FakeKeyguardTransitionRepository()
+ mainExecutor = FakeExecutor(clock)
+ backgroundExecutor = FakeExecutor(clock)
mediaCarouselController =
MediaCarouselController(
context,
@@ -126,7 +129,8 @@ class MediaCarouselControllerTest : SysuiTestCase() {
mediaHostStatesManager,
activityStarter,
clock,
- executor,
+ mainExecutor,
+ backgroundExecutor,
mediaDataManager,
configurationController,
falsingCollector,
@@ -401,6 +405,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
resumption = true
)
)
+ runAllReady()
assertEquals(
MediaPlayerData.getMediaPlayerIndex("paused local"),
@@ -510,6 +515,8 @@ class MediaCarouselControllerTest : SysuiTestCase() {
false
)
mediaCarouselController.shouldScrollToKey = true
+ runAllReady()
+
// switching between media players.
listener.value.onMediaDataLoaded(
"playing local",
@@ -531,6 +538,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
resumption = false
)
)
+ runAllReady()
assertEquals(
MediaPlayerData.getMediaPlayerIndex("paused local"),
@@ -555,6 +563,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
resumption = false
)
)
+ runAllReady()
var playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local")
assertEquals(
@@ -577,6 +586,8 @@ class MediaCarouselControllerTest : SysuiTestCase() {
packageName = "PACKAGE_NAME"
)
)
+ runAllReady()
+
playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local")
assertEquals(playerIndex, 0)
}
@@ -673,17 +684,38 @@ class MediaCarouselControllerTest : SysuiTestCase() {
}
@Test
- fun testOnConfigChanged_playersAreAddedBack() {
+ fun testOnUiModeChanged_playersAreAddedBack() {
+ mediaCarouselController.pageIndicator = pageIndicator
+
listener.value.onMediaDataLoaded(
- "playing local",
+ "paused local",
null,
DATA.copy(
active = true,
- isPlaying = true,
+ isPlaying = false,
playbackLocation = MediaData.PLAYBACK_LOCAL,
resumption = false
)
)
+ runAllReady()
+
+ val playersSize = MediaPlayerData.players().size
+ configListener.value.onUiModeChanged()
+ runAllReady()
+
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+ assertEquals(playersSize, MediaPlayerData.players().size)
+ assertEquals(
+ MediaPlayerData.getMediaPlayerIndex("paused local"),
+ mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
+ )
+ }
+
+ @Test
+ fun testOnDensityOrFontScaleChanged_playersAreAddedBack() {
+ mediaCarouselController.pageIndicator = pageIndicator
+
listener.value.onMediaDataLoaded(
"paused local",
null,
@@ -694,14 +726,46 @@ class MediaCarouselControllerTest : SysuiTestCase() {
resumption = false
)
)
+ runAllReady()
val playersSize = MediaPlayerData.players().size
+ configListener.value.onDensityOrFontScaleChanged()
+ runAllReady()
+
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+ assertEquals(playersSize, MediaPlayerData.players().size)
+ assertEquals(
+ MediaPlayerData.getMediaPlayerIndex("paused local"),
+ mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
+ )
+ }
- configListener.value.onConfigChanged(Configuration())
+ @Test
+ fun testOnThemeChanged_playersAreAddedBack() {
+ mediaCarouselController.pageIndicator = pageIndicator
+ listener.value.onMediaDataLoaded(
+ "paused local",
+ null,
+ DATA.copy(
+ active = true,
+ isPlaying = false,
+ playbackLocation = MediaData.PLAYBACK_LOCAL,
+ resumption = false
+ )
+ )
+ runAllReady()
+
+ val playersSize = MediaPlayerData.players().size
+ configListener.value.onThemeChanged()
+ runAllReady()
+
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
assertEquals(playersSize, MediaPlayerData.players().size)
assertEquals(
- MediaPlayerData.getMediaPlayerIndex("playing local"),
+ MediaPlayerData.getMediaPlayerIndex("paused local"),
mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
)
}
@@ -832,4 +896,9 @@ class MediaCarouselControllerTest : SysuiTestCase() {
// Verify that seekbar listening attribute in media control panel is set to false.
verify(panel, times(MediaPlayerData.players().size)).listening = false
}
+
+ private fun runAllReady() {
+ backgroundExecutor.runAllReady()
+ mainExecutor.runAllReady()
+ }
}
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 55a33b6636e0..fd353afff7c0 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
@@ -27,6 +27,7 @@ import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
+import android.graphics.Matrix
import android.graphics.drawable.Animatable2
import android.graphics.drawable.AnimatedVectorDrawable
import android.graphics.drawable.Drawable
@@ -78,6 +79,8 @@ import com.android.systemui.media.controls.pipeline.EMPTY_SMARTSPACE_MEDIA_DATA
import com.android.systemui.media.controls.pipeline.MediaDataManager
import com.android.systemui.media.controls.util.MediaUiEventLogger
import com.android.systemui.media.dialog.MediaOutputDialogFactory
+import com.android.systemui.monet.ColorScheme
+import com.android.systemui.monet.Style
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.NotificationLockscreenUserManager
@@ -214,6 +217,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
@Mock private lateinit var recSubtitleMock2: TextView
@Mock private lateinit var recSubtitleMock3: TextView
@Mock private lateinit var coverItem: ImageView
+ @Mock private lateinit var matrix: Matrix
private lateinit var coverItem1: ImageView
private lateinit var coverItem2: ImageView
private lateinit var coverItem3: ImageView
@@ -700,6 +704,46 @@ public class MediaControlPanelTest : SysuiTestCase() {
}
@Test
+ fun addTwoPlayerGradients_differentStates() {
+ // Setup redArtwork and its color scheme.
+ val redBmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+ val redCanvas = Canvas(redBmp)
+ redCanvas.drawColor(Color.RED)
+ val redArt = Icon.createWithBitmap(redBmp)
+ val redWallpaperColor = player.getWallpaperColor(redArt)
+ val redColorScheme = ColorScheme(redWallpaperColor, true, Style.CONTENT)
+
+ // Setup greenArt and its color scheme.
+ val greenBmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+ val greenCanvas = Canvas(greenBmp)
+ greenCanvas.drawColor(Color.GREEN)
+ val greenArt = Icon.createWithBitmap(greenBmp)
+ val greenWallpaperColor = player.getWallpaperColor(greenArt)
+ val greenColorScheme = ColorScheme(greenWallpaperColor, true, Style.CONTENT)
+
+ // Add gradient to both icons.
+ val redArtwork = player.addGradientToPlayerAlbum(redArt, redColorScheme, 10, 10)
+ val greenArtwork = player.addGradientToPlayerAlbum(greenArt, greenColorScheme, 10, 10)
+
+ // They should have different constant states as they have different gradient color.
+ assertThat(redArtwork.getDrawable(1).constantState)
+ .isNotEqualTo(greenArtwork.getDrawable(1).constantState)
+ }
+
+ @Test
+ fun getWallpaperColor_recycledBitmap_notCrashing() {
+ // Setup redArt icon.
+ val redBmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+ val redArt = Icon.createWithBitmap(redBmp)
+
+ // Recycle bitmap of redArt icon.
+ redArt.bitmap.recycle()
+
+ // get wallpaperColor without illegal exception.
+ player.getWallpaperColor(redArt)
+ }
+
+ @Test
fun bind_seekBarDisabled_hasActions_seekBarVisibilityIsSetToInvisible() {
useRealConstraintSets()
@@ -2092,6 +2136,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
.thenReturn(listOf(recProgressBar1, recProgressBar2, recProgressBar3))
whenever(recommendationViewHolder.mediaSubtitles)
.thenReturn(listOf(recSubtitleMock1, recSubtitleMock2, recSubtitleMock3))
+ whenever(coverItem.imageMatrix).thenReturn(matrix)
val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bmp)
@@ -2127,6 +2172,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
verify(recCardTitle).setTextColor(any<Int>())
verify(recAppIconItem, times(3)).setImageDrawable(any(Drawable::class.java))
verify(coverItem, times(3)).setImageDrawable(any(Drawable::class.java))
+ verify(coverItem, times(3)).imageMatrix = any()
}
@Test
@@ -2189,6 +2235,34 @@ public class MediaControlPanelTest : SysuiTestCase() {
}
@Test
+ fun addTwoRecommendationGradients_differentStates() {
+ // Setup redArtwork and its color scheme.
+ val redBmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+ val redCanvas = Canvas(redBmp)
+ redCanvas.drawColor(Color.RED)
+ val redArt = Icon.createWithBitmap(redBmp)
+ val redWallpaperColor = player.getWallpaperColor(redArt)
+ val redColorScheme = ColorScheme(redWallpaperColor, true, Style.CONTENT)
+
+ // Setup greenArt and its color scheme.
+ val greenBmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+ val greenCanvas = Canvas(greenBmp)
+ greenCanvas.drawColor(Color.GREEN)
+ val greenArt = Icon.createWithBitmap(greenBmp)
+ val greenWallpaperColor = player.getWallpaperColor(greenArt)
+ val greenColorScheme = ColorScheme(greenWallpaperColor, true, Style.CONTENT)
+
+ // Add gradient to both icons.
+ val redArtwork = player.addGradientToRecommendationAlbum(redArt, redColorScheme, 10, 10)
+ val greenArtwork =
+ player.addGradientToRecommendationAlbum(greenArt, greenColorScheme, 10, 10)
+
+ // They should have different constant states as they have different gradient color.
+ assertThat(redArtwork.getDrawable(1).constantState)
+ .isNotEqualTo(greenArtwork.getDrawable(1).constantState)
+ }
+
+ @Test
fun onButtonClick_touchRippleFlagEnabled_playsTouchRipple() {
fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
val semanticActions =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
index a5795184b493..feb429d2f0d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
@@ -180,6 +180,57 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
}
@Test
+ fun testBlockedWhenConfigurationChangesAndScreenOff() {
+ // Let's set it onto QS:
+ mediaHierarchyManager.qsExpansion = 1.0f
+ verify(mediaCarouselController)
+ .onDesiredLocationChanged(
+ ArgumentMatchers.anyInt(),
+ any(MediaHostState::class.java),
+ anyBoolean(),
+ anyLong(),
+ anyLong()
+ )
+ val observer = wakefullnessObserver.value
+ assertNotNull("lifecycle observer wasn't registered", observer)
+ observer.onStartedGoingToSleep()
+ clearInvocations(mediaCarouselController)
+ configurationController.notifyConfigurationChanged()
+ verify(mediaCarouselController, times(0))
+ .onDesiredLocationChanged(
+ ArgumentMatchers.anyInt(),
+ any(MediaHostState::class.java),
+ anyBoolean(),
+ anyLong(),
+ anyLong()
+ )
+ }
+
+ @Test
+ fun testAllowedWhenConfigurationChanges() {
+ // Let's set it onto QS:
+ mediaHierarchyManager.qsExpansion = 1.0f
+ verify(mediaCarouselController)
+ .onDesiredLocationChanged(
+ ArgumentMatchers.anyInt(),
+ any(MediaHostState::class.java),
+ anyBoolean(),
+ anyLong(),
+ anyLong()
+ )
+ clearInvocations(mediaCarouselController)
+ configurationController.notifyConfigurationChanged()
+ verify(mediaCarouselController)
+ .onDesiredLocationChanged(
+ ArgumentMatchers.anyInt(),
+ any(MediaHostState::class.java),
+ anyBoolean(),
+ anyLong(),
+ anyLong()
+ )
+ }
+
+ @Test
fun testAllowedWhenNotTurningOff() {
// Let's set it onto QS:
mediaHierarchyManager.qsExpansion = 1.0f
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
index af91cdb1522c..0fac3db2dc1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
@@ -16,9 +16,12 @@
package com.android.systemui.media.controls.ui
+import android.content.res.Configuration
+import android.content.res.Configuration.ORIENTATION_LANDSCAPE
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.View
+import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
@@ -58,6 +61,8 @@ class MediaViewControllerTest : SysuiTestCase() {
@Mock private lateinit var mediaSubTitleWidgetState: WidgetState
@Mock private lateinit var mediaContainerWidgetState: WidgetState
@Mock private lateinit var mediaFlags: MediaFlags
+ @Mock private lateinit var expandedLayout: ConstraintSet
+ @Mock private lateinit var collapsedLayout: ConstraintSet
val delta = 0.1F
@@ -77,6 +82,19 @@ class MediaViewControllerTest : SysuiTestCase() {
}
@Test
+ fun testOrientationChanged_layoutsAreLoaded() {
+ mediaViewController.expandedLayout = expandedLayout
+ mediaViewController.collapsedLayout = collapsedLayout
+
+ val newConfig = Configuration()
+ newConfig.orientation = ORIENTATION_LANDSCAPE
+ configurationController.onConfigurationChanged(newConfig)
+
+ verify(expandedLayout).load(context, R.xml.media_session_expanded)
+ verify(collapsedLayout).load(context, R.xml.media_session_collapsed)
+ }
+
+ @Test
fun testObtainViewState_applySquishFraction_toPlayerTransitionViewState_height() {
mediaViewController.attach(player, MediaViewController.TYPE.PLAYER)
player.measureState =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
index 4fc9ca71aeaa..85e8d072bd99 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
@@ -70,8 +70,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = null,
isReceiver = false,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -86,8 +85,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = null,
isReceiver = true,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -119,8 +117,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = "fakePackageName",
isReceiver = false,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -135,8 +132,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = "fakePackageName",
isReceiver = true,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -154,7 +150,9 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = "fakePackageName",
isReceiver = false
- ) { exceptionTriggered = true }
+ ) {
+ exceptionTriggered = true
+ }
assertThat(exceptionTriggered).isTrue()
}
@@ -167,7 +165,9 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = "fakePackageName",
isReceiver = true
- ) { exceptionTriggered = true }
+ ) {
+ exceptionTriggered = true
+ }
assertThat(exceptionTriggered).isTrue()
}
@@ -179,8 +179,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
PACKAGE_NAME,
isReceiver = false,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isTrue()
assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
@@ -194,8 +193,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
PACKAGE_NAME,
isReceiver = true,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isTrue()
assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
index db890f6e739b..ca2b1da34766 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
@@ -107,6 +107,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
private lateinit var fakeExecutor: FakeExecutor
private lateinit var uiEventLoggerFake: UiEventLoggerFake
private lateinit var uiEventLogger: MediaTttSenderUiEventLogger
+ private val defaultTimeout = context.resources.getInteger(R.integer.heads_up_notification_decay)
@Before
fun setUp() {
@@ -1356,6 +1357,92 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.VISIBLE)
}
+ @Test
+ fun almostClose_hasLongTimeout_eventuallyTimesOut() {
+ whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenAnswer {
+ it.arguments[0]
+ }
+
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
+ routeInfo,
+ null,
+ )
+
+ // WHEN the default timeout has passed
+ fakeClock.advanceTime(defaultTimeout + 1L)
+
+ // THEN the view is still on-screen because it has a long timeout
+ verify(windowManager, never()).removeView(any())
+
+ // WHEN a very long amount of time has passed
+ fakeClock.advanceTime(5L * defaultTimeout)
+
+ // THEN the view does time out
+ verify(windowManager).removeView(any())
+ }
+
+ @Test
+ fun loading_hasLongTimeout_eventuallyTimesOut() {
+ whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenAnswer {
+ it.arguments[0]
+ }
+
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
+ routeInfo,
+ null,
+ )
+
+ // WHEN the default timeout has passed
+ fakeClock.advanceTime(defaultTimeout + 1L)
+
+ // THEN the view is still on-screen because it has a long timeout
+ verify(windowManager, never()).removeView(any())
+
+ // WHEN a very long amount of time has passed
+ fakeClock.advanceTime(5L * defaultTimeout)
+
+ // THEN the view does time out
+ verify(windowManager).removeView(any())
+ }
+
+ @Test
+ fun succeeded_hasDefaultTimeout() {
+ whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenAnswer {
+ it.arguments[0]
+ }
+
+ displayReceiverTriggered()
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
+ routeInfo,
+ null,
+ )
+
+ fakeClock.advanceTime(defaultTimeout + 1L)
+
+ verify(windowManager).removeView(any())
+ }
+
+ @Test
+ fun failed_hasDefaultTimeout() {
+ whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenAnswer {
+ it.arguments[0]
+ }
+
+ displayThisDeviceTriggered()
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED,
+ routeInfo,
+ null,
+ )
+
+ fakeClock.advanceTime(defaultTimeout + 1L)
+
+ verify(windowManager).removeView(any())
+ }
+
private fun getChipbarView(): ViewGroup {
val viewCaptor = ArgumentCaptor.forClass(View::class.java)
verify(windowManager).addView(viewCaptor.capture(), any())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
index ce6a98c9e162..9b8605dccd09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
@@ -35,6 +35,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
+import android.view.IWindowManager;
import android.view.accessibility.AccessibilityManager;
import androidx.test.filters.SmallTest;
@@ -46,7 +47,9 @@ import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
import com.android.systemui.accessibility.SystemActions;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.CentralSurfaces;
@@ -101,6 +104,14 @@ public class NavBarHelperTest extends SysuiTestCase {
NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater;
@Mock
CommandQueue mCommandQueue;
+ @Mock
+ IWindowManager mWm;
+ @Mock
+ DisplayTracker mDisplayTracker;
+ @Mock
+ EdgeBackGestureHandler mEdgeBackGestureHandler;
+ @Mock
+ EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
private AccessibilityManager.AccessibilityServicesStateChangeListener
mAccessibilityServicesStateChangeListener;
@@ -114,6 +125,8 @@ public class NavBarHelperTest extends SysuiTestCase {
when(mAssistManagerLazy.get()).thenReturn(mAssistManager);
when(mAssistManager.getAssistInfoForUser(anyInt())).thenReturn(mAssistantComponent);
when(mUserTracker.getUserId()).thenReturn(1);
+ when(mDisplayTracker.getDefaultDisplayId()).thenReturn(0);
+ when(mEdgeBackGestureHandlerFactory.create(any())).thenReturn(mEdgeBackGestureHandler);
doAnswer((invocation) -> mAccessibilityServicesStateChangeListener =
invocation.getArgument(0)).when(
@@ -122,36 +135,70 @@ public class NavBarHelperTest extends SysuiTestCase {
mAccessibilityButtonModeObserver, mAccessibilityButtonTargetObserver,
mSystemActions, mOverviewProxyService, mAssistManagerLazy,
() -> Optional.of(mock(CentralSurfaces.class)), mock(KeyguardStateController.class),
- mNavigationModeController, mUserTracker, mDumpManager, mCommandQueue);
+ mNavigationModeController, mEdgeBackGestureHandlerFactory, mWm, mUserTracker,
+ mDisplayTracker, mDumpManager, mCommandQueue);
}
@Test
public void registerListenersInCtor() {
- verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper);
verify(mNavigationModeController, times(1)).addListener(mNavBarHelper);
verify(mOverviewProxyService, times(1)).addCallback(mNavBarHelper);
+ verify(mCommandQueue, times(1)).addCallback(any());
}
@Test
- public void registerAssistantContentObserver() {
- mNavBarHelper.init();
+ public void testSetupBarsRegistersListeners() throws Exception {
+ mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+ verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper);
+ verify(mAccessibilityButtonTargetObserver, times(1)).addListener(mNavBarHelper);
+ verify(mAccessibilityManager, times(1)).addAccessibilityServicesStateChangeListener(
+ mNavBarHelper);
verify(mAssistManager, times(1)).getAssistInfoForUser(anyInt());
+ verify(mWm, times(1)).watchRotation(any(), anyInt());
+ verify(mWm, times(1)).registerWallpaperVisibilityListener(any(), anyInt());
+ verify(mEdgeBackGestureHandler, times(1)).onNavBarAttached();
+ }
+
+ @Test
+ public void testCleanupBarsUnregistersListeners() throws Exception {
+ mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+ mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+ verify(mAccessibilityButtonModeObserver, times(1)).removeListener(mNavBarHelper);
+ verify(mAccessibilityButtonTargetObserver, times(1)).removeListener(mNavBarHelper);
+ verify(mAccessibilityManager, times(1)).removeAccessibilityServicesStateChangeListener(
+ mNavBarHelper);
+ verify(mWm, times(1)).removeRotationWatcher(any());
+ verify(mWm, times(1)).unregisterWallpaperVisibilityListener(any(), anyInt());
+ verify(mEdgeBackGestureHandler, times(1)).onNavBarDetached();
+ }
+
+ @Test
+ public void replacingBarsHint() {
+ mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+ mNavBarHelper.setTogglingNavbarTaskbar(true);
+ mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+ mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+ mNavBarHelper.setTogglingNavbarTaskbar(false);
+ // Use any state in cleanup to verify it was not called
+ verify(mAccessibilityButtonModeObserver, times(0)).removeListener(mNavBarHelper);
}
@Test
public void callbacksFiredWhenRegistering() {
- mNavBarHelper.init();
mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
verify(mNavbarTaskbarStateUpdater, times(1))
.updateAccessibilityServicesState();
verify(mNavbarTaskbarStateUpdater, times(1))
.updateAssistantAvailable(anyBoolean(), anyBoolean());
+ verify(mNavbarTaskbarStateUpdater, times(1))
+ .updateRotationWatcherState(anyInt());
+ verify(mNavbarTaskbarStateUpdater, times(1))
+ .updateWallpaperVisibility(anyBoolean(), anyInt());
}
@Test
public void assistantCallbacksFiredAfterConnecting() {
- mNavBarHelper.init();
// 1st set of callbacks get called when registering
mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
@@ -172,7 +219,6 @@ public class NavBarHelperTest extends SysuiTestCase {
@Test
public void a11yCallbacksFiredAfterModeChange() {
- mNavBarHelper.init();
// 1st set of callbacks get called when registering
mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
@@ -185,7 +231,6 @@ public class NavBarHelperTest extends SysuiTestCase {
@Test
public void assistantCallbacksFiredAfterNavModeChange() {
- mNavBarHelper.init();
// 1st set of callbacks get called when registering
mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
@@ -198,7 +243,6 @@ public class NavBarHelperTest extends SysuiTestCase {
@Test
public void removeListenerNoCallbacksFired() {
- mNavBarHelper.init();
// 1st set of callbacks get called when registering
mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
@@ -220,7 +264,7 @@ public class NavBarHelperTest extends SysuiTestCase {
when(mAccessibilityManager.getAccessibilityShortcutTargets(
AccessibilityManager.ACCESSIBILITY_BUTTON)).thenReturn(createFakeShortcutTargets());
- mNavBarHelper.init();
+ mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
assertThat(mNavBarHelper.getA11yButtonState()).isEqualTo(
ACCESSIBILITY_BUTTON_CLICKABLE_STATE);
@@ -230,13 +274,15 @@ public class NavBarHelperTest extends SysuiTestCase {
public void initAccessibilityStateWithFloatingMenuModeAndTargets_disableClickableState() {
when(mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()).thenReturn(
ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
- mNavBarHelper.init();
+
+ mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
assertThat(mNavBarHelper.getA11yButtonState()).isEqualTo(/* disable_clickable_state */ 0);
}
@Test
public void onA11yServicesStateChangedWithMultipleServices_a11yButtonClickableState() {
+ mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
when(mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()).thenReturn(
ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
@@ -250,14 +296,7 @@ public class NavBarHelperTest extends SysuiTestCase {
}
@Test
- public void registerCommandQueueCallbacks() {
- mNavBarHelper.init();
- verify(mCommandQueue, times(1)).addCallback(any());
- }
-
- @Test
public void saveMostRecentSysuiState() {
- mNavBarHelper.init();
mNavBarHelper.setWindowState(DISPLAY_ID, WINDOW, STATE_ID);
NavBarHelper.CurrentSysuiState state1 = mNavBarHelper.getCurrentSysuiState();
@@ -274,7 +313,6 @@ public class NavBarHelperTest extends SysuiTestCase {
@Test
public void ignoreNonNavbarSysuiState() {
- mNavBarHelper.init();
mNavBarHelper.setWindowState(DISPLAY_ID, WINDOW, STATE_ID);
NavBarHelper.CurrentSysuiState state1 = mNavBarHelper.getCurrentSysuiState();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index aacbf8f2adeb..0a91a0ed0532 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -143,8 +143,8 @@ public class NavigationBarControllerTest extends SysuiTestCase {
@Test
public void testCreateNavigationBarsIncludeDefaultTrue() {
- // Tablets may be using taskbar and the logic is different
- mNavigationBarController.mIsTablet = false;
+ // Large screens may be using taskbar and the logic is different
+ mNavigationBarController.mIsLargeScreen = false;
doNothing().when(mNavigationBarController).createNavigationBar(any(), any(), any());
mNavigationBarController.createNavigationBars(true, null);
@@ -292,7 +292,7 @@ public class NavigationBarControllerTest extends SysuiTestCase {
@Test
public void testConfigurationChange_taskbarNotInitialized() {
Configuration configuration = mContext.getResources().getConfiguration();
- when(Utilities.isTablet(any())).thenReturn(true);
+ when(Utilities.isLargeScreen(any())).thenReturn(true);
mNavigationBarController.onConfigChanged(configuration);
verify(mTaskbarDelegate, never()).onConfigurationChanged(configuration);
}
@@ -300,7 +300,7 @@ public class NavigationBarControllerTest extends SysuiTestCase {
@Test
public void testConfigurationChange_taskbarInitialized() {
Configuration configuration = mContext.getResources().getConfiguration();
- when(Utilities.isTablet(any())).thenReturn(true);
+ when(Utilities.isLargeScreen(any())).thenReturn(true);
when(mTaskbarDelegate.isInitialized()).thenReturn(true);
mNavigationBarController.onConfigChanged(configuration);
verify(mTaskbarDelegate, times(1)).onConfigurationChanged(configuration);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index 764ddc49d110..f062ec732b21 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -58,6 +58,7 @@ import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.IWindowManager;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewRootImpl;
@@ -87,6 +88,7 @@ import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
+import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.settings.UserContextProvider;
import com.android.systemui.settings.UserTracker;
@@ -172,8 +174,6 @@ public class NavigationBarTest extends SysuiTestCase {
private UiEventLogger mUiEventLogger;
@Mock
private ViewTreeObserver mViewTreeObserver;
- @Mock
- EdgeBackGestureHandler mEdgeBackGestureHandler;
NavBarHelper mNavBarHelper;
@Mock
private LightBarController mLightBarController;
@@ -205,6 +205,10 @@ public class NavigationBarTest extends SysuiTestCase {
private Resources mResources;
@Mock
private ViewRootImpl mViewRootImpl;
+ @Mock
+ private EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+ @Mock
+ private EdgeBackGestureHandler mEdgeBackGestureHandler;
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
private DeviceConfigProxyFake mDeviceConfigProxyFake = new DeviceConfigProxyFake();
private TaskStackChangeListeners mTaskStackChangeListeners =
@@ -234,6 +238,7 @@ public class NavigationBarTest extends SysuiTestCase {
.thenReturn(mContext);
when(mNavigationBarView.getResources()).thenReturn(mResources);
when(mNavigationBarView.getViewRootImpl()).thenReturn(mViewRootImpl);
+ when(mEdgeBackGestureHandlerFactory.create(any())).thenReturn(mEdgeBackGestureHandler);
setupSysuiDependency();
// This class inflates views that call Dependency.get, thus these injections are still
// necessary.
@@ -250,7 +255,9 @@ public class NavigationBarTest extends SysuiTestCase {
mSystemActions, mOverviewProxyService,
() -> mock(AssistManager.class), () -> Optional.of(mCentralSurfaces),
mKeyguardStateController, mock(NavigationModeController.class),
- mock(UserTracker.class), mock(DumpManager.class), mock(CommandQueue.class)));
+ mEdgeBackGestureHandlerFactory, mock(IWindowManager.class),
+ mock(UserTracker.class), mock(DisplayTracker.class), mock(DumpManager.class),
+ mock(CommandQueue.class)));
mNavigationBar = createNavBar(mContext);
mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal);
});
@@ -492,7 +499,6 @@ public class NavigationBarTest extends SysuiTestCase {
mDeadZone,
mDeviceConfigProxyFake,
mNavigationBarTransitions,
- mEdgeBackGestureHandler,
Optional.of(mock(BackAnimation.class)),
mUserContextProvider,
mWakefulnessLifecycle,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
index 5270737b7f3e..54aec3014f95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
@@ -27,7 +27,6 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
-import android.view.IWindowManager;
import androidx.test.filters.SmallTest;
@@ -60,8 +59,6 @@ public class NavigationBarTransitionsTest extends SysuiTestCase {
EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
@Mock
EdgeBackGestureHandler mEdgeBackGestureHandler;
- @Mock
- IWindowManager mIWindowManager;
private NavigationBarTransitions mTransitions;
private final FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
@@ -88,7 +85,7 @@ public class NavigationBarTransitionsTest extends SysuiTestCase {
when(navBar.getCurrentView()).thenReturn(navBar);
when(navBar.findViewById(anyInt())).thenReturn(navBar);
mTransitions = new NavigationBarTransitions(
- navBar, mIWindowManager, mLightBarTransitionsFactory, mDisplayTracker);
+ navBar, mLightBarTransitionsFactory, mDisplayTracker);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
index 537dfb821fef..8d01e80d37d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
@@ -13,6 +13,7 @@ import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.phone.AutoHideController
import com.android.systemui.statusbar.phone.LightBarController
import com.android.systemui.statusbar.phone.LightBarTransitionsController
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.wm.shell.back.BackAnimation
import com.android.wm.shell.pip.Pip
import org.junit.Before
@@ -37,8 +38,6 @@ class TaskbarDelegateTest : SysuiTestCase() {
private lateinit var mTaskStackChangeListeners: TaskStackChangeListeners
private lateinit var mTaskbarDelegate: TaskbarDelegate
@Mock
- lateinit var mEdgeBackGestureHandlerFactory : EdgeBackGestureHandler.Factory
- @Mock
lateinit var mEdgeBackGestureHandler : EdgeBackGestureHandler
@Mock
lateinit var mLightBarControllerFactory : LightBarTransitionsController.Factory
@@ -66,17 +65,19 @@ class TaskbarDelegateTest : SysuiTestCase() {
lateinit var mBackAnimation: BackAnimation
@Mock
lateinit var mCurrentSysUiState: NavBarHelper.CurrentSysuiState
+ @Mock
+ lateinit var mStatusBarKeyguardViewManager: StatusBarKeyguardViewManager
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- `when`(mEdgeBackGestureHandlerFactory.create(context)).thenReturn(mEdgeBackGestureHandler)
+ `when`(mNavBarHelper.edgeBackGestureHandler).thenReturn(mEdgeBackGestureHandler)
`when`(mLightBarControllerFactory.create(any())).thenReturn(mLightBarTransitionController)
`when`(mNavBarHelper.currentSysuiState).thenReturn(mCurrentSysUiState)
`when`(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState)
mTaskStackChangeListeners = TaskStackChangeListeners.getTestInstance()
- mTaskbarDelegate = TaskbarDelegate(context, mEdgeBackGestureHandlerFactory,
- mLightBarControllerFactory)
+ mTaskbarDelegate = TaskbarDelegate(context, mLightBarControllerFactory,
+ mStatusBarKeyguardViewManager)
mTaskbarDelegate.setDependencies(mCommandQueue, mOverviewProxyService, mNavBarHelper,
mNavigationModeController, mSysUiState, mDumpManager, mAutoHideController,
mLightBarController, mOptionalPip, mBackAnimation, mTaskStackChangeListeners)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/process/condition/UserProcessConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java
index 2293fc577029..fb7197706ddc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/process/condition/UserProcessConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java
@@ -26,7 +26,6 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.process.ProcessWrapper;
-import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.condition.Condition;
import com.android.systemui.shared.condition.Monitor;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -41,10 +40,7 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
-public class UserProcessConditionTest extends SysuiTestCase {
- @Mock
- UserTracker mUserTracker;
-
+public class SystemProcessConditionTest extends SysuiTestCase {
@Mock
ProcessWrapper mProcessWrapper;
@@ -59,15 +55,14 @@ public class UserProcessConditionTest extends SysuiTestCase {
}
/**
- * Verifies condition reports false when tracker reports a different user id than the
- * identifier from the process handle.
+ * Verifies condition reports false when tracker reports the process is being ran by the
+ * system user.
*/
@Test
- public void testConditionFailsWithDifferentIds() {
+ public void testConditionFailsWithNonSystemProcess() {
- final Condition condition = new UserProcessCondition(mProcessWrapper, mUserTracker);
- when(mProcessWrapper.getUserHandleIdentifier()).thenReturn(0);
- when(mUserTracker.getUserId()).thenReturn(1);
+ final Condition condition = new SystemProcessCondition(mProcessWrapper);
+ when(mProcessWrapper.isSystemUser()).thenReturn(false);
final Monitor monitor = new Monitor(mExecutor);
@@ -81,15 +76,14 @@ public class UserProcessConditionTest extends SysuiTestCase {
}
/**
- * Verifies condition reports false when tracker reports a different user id than the
- * identifier from the process handle.
+ * Verifies condition reports true when tracker reports the process is being ran by the
+ * system user.
*/
@Test
- public void testConditionSucceedsWithSameIds() {
+ public void testConditionSucceedsWithSystemProcess() {
- final Condition condition = new UserProcessCondition(mProcessWrapper, mUserTracker);
- when(mProcessWrapper.getUserHandleIdentifier()).thenReturn(0);
- when(mUserTracker.getUserId()).thenReturn(0);
+ final Condition condition = new SystemProcessCondition(mProcessWrapper);
+ when(mProcessWrapper.isSystemUser()).thenReturn(true);
final Monitor monitor = new Monitor(mExecutor);
@@ -101,5 +95,4 @@ public class UserProcessConditionTest extends SysuiTestCase {
verify(mCallback).onConditionsChanged(true);
}
-
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 4caa50fa847d..0ab0e2b4b9f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -52,15 +52,17 @@ import com.android.systemui.R;
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.media.controls.ui.MediaHost;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
import com.android.systemui.qs.external.TileServiceRequestController;
import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder;
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
+import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.FakeDisplayTracker;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -86,7 +88,6 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
@Mock private MediaHost mQSMediaHost;
@Mock private MediaHost mQQSMediaHost;
@Mock private KeyguardBypassController mBypassController;
- @Mock private FalsingManager mFalsingManager;
@Mock private TileServiceRequestController.Builder mTileServiceRequestControllerBuilder;
@Mock private TileServiceRequestController mTileServiceRequestController;
@Mock private QSCustomizerController mQsCustomizerController;
@@ -105,6 +106,8 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
@Mock private QSSquishinessController mSquishinessController;
@Mock private FooterActionsViewModel mFooterActionsViewModel;
@Mock private FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
+ @Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
+ @Mock private FeatureFlags mFeatureFlags;
private View mQsFragmentView;
public QSFragmentTest() {
@@ -150,8 +153,9 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
}
@Test
- public void transitionToFullShade_setsAlphaUsingShadeInterpolator() {
+ public void transitionToFullShade_smallScreen_alphaAlways1() {
QSFragment fragment = resumeAndGetFragment();
+ setIsSmallScreen();
setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE);
boolean isTransitioningToFullShade = true;
float transitionProgress = 0.5f;
@@ -160,6 +164,43 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
squishinessFraction);
+ assertThat(mQsFragmentView.getAlpha()).isEqualTo(1f);
+ }
+
+ @Test
+ public void transitionToFullShade_largeScreen_flagEnabled_alphaLargeScreenShadeInterpolator() {
+ when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+ .thenReturn(true);
+ QSFragment fragment = resumeAndGetFragment();
+ setIsLargeScreen();
+ setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE);
+ boolean isTransitioningToFullShade = true;
+ float transitionProgress = 0.5f;
+ float squishinessFraction = 0.5f;
+ when(mLargeScreenShadeInterpolator.getQsAlpha(transitionProgress)).thenReturn(123f);
+
+ fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+ squishinessFraction);
+
+ assertThat(mQsFragmentView.getAlpha())
+ .isEqualTo(123f);
+ }
+
+ @Test
+ public void transitionToFullShade_largeScreen_flagDisabled_alphaStandardInterpolator() {
+ when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+ .thenReturn(false);
+ QSFragment fragment = resumeAndGetFragment();
+ setIsLargeScreen();
+ setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE);
+ boolean isTransitioningToFullShade = true;
+ float transitionProgress = 0.5f;
+ float squishinessFraction = 0.5f;
+ when(mLargeScreenShadeInterpolator.getQsAlpha(transitionProgress)).thenReturn(123f);
+
+ fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+ squishinessFraction);
+
assertThat(mQsFragmentView.getAlpha())
.isEqualTo(ShadeInterpolation.getContentAlpha(transitionProgress));
}
@@ -503,11 +544,9 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
setUpMedia();
setUpOther();
- FakeFeatureFlags featureFlags = new FakeFeatureFlags();
return new QSFragment(
new RemoteInputQuickSettingsDisabler(
context, commandQueue, mock(ConfigurationController.class)),
- mock(QSTileHost.class),
mStatusBarStateController,
commandQueue,
mQSMediaHost,
@@ -515,11 +554,12 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
mBypassController,
mQsComponentFactory,
mock(QSFragmentDisableFlagsLogger.class),
- mFalsingManager,
mock(DumpManager.class),
- featureFlags,
+ mock(QSLogger.class),
mock(FooterActionsController.class),
- mFooterActionsViewModelFactory);
+ mFooterActionsViewModelFactory,
+ mLargeScreenShadeInterpolator,
+ mFeatureFlags);
}
private void setUpOther() {
@@ -627,4 +667,12 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
return null;
}).when(view).getLocationOnScreen(any(int[].class));
}
+
+ private void setIsLargeScreen() {
+ getFragment().setIsNotificationPanelFullWidth(false);
+ }
+
+ private void setIsSmallScreen() {
+ getFragment().setIsNotificationPanelFullWidth(true);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index 5058373e39b0..3d55c5131b40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -71,7 +71,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
@Mock
private QSPanel mQSPanel;
@Mock
- private QSTileHost mQSTileHost;
+ private QSHost mQSHost;
@Mock
private QSCustomizerController mQSCustomizerController;
@Mock
@@ -105,7 +105,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
/** Implementation needed to ensure we have a reflectively-available class name. */
private class TestableQSPanelControllerBase extends QSPanelControllerBase<QSPanel> {
- protected TestableQSPanelControllerBase(QSPanel view, QSTileHost host,
+ protected TestableQSPanelControllerBase(QSPanel view, QSHost host,
QSCustomizerController qsCustomizerController, MediaHost mediaHost,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
DumpManager dumpManager) {
@@ -130,8 +130,8 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
when(mQSPanel.getOrCreateTileLayout()).thenReturn(mPagedTileLayout);
when(mQSPanel.getTileLayout()).thenReturn(mPagedTileLayout);
when(mQSTile.getTileSpec()).thenReturn("dnd");
- when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
- when(mQSTileHost.createTileView(any(), eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
+ when(mQSHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
+ when(mQSHost.createTileView(any(), eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
when(mQSTileRevealControllerFactory.create(any(), any()))
.thenReturn(mQSTileRevealController);
when(mMediaHost.getDisappearParameters()).thenReturn(new DisappearParameters());
@@ -142,7 +142,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
return null;
}).when(mQSPanel).setListening(anyBoolean());
- mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
+ mController = new TestableQSPanelControllerBase(mQSPanel, mQSHost,
mQSCustomizerController, mMediaHost,
mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
@@ -155,7 +155,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
mController.onViewDetached();
QSPanelControllerBase<QSPanel> controller = new TestableQSPanelControllerBase(mQSPanel,
- mQSTileHost, mQSCustomizerController, mMediaHost,
+ mQSHost, mQSCustomizerController, mMediaHost,
mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager) {
@Override
protected QSTileRevealController createTileRevealController() {
@@ -250,7 +250,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(false);
when(mQSPanel.getDumpableTag()).thenReturn("QSPanelLandscape");
- mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
+ mController = new TestableQSPanelControllerBase(mQSPanel, mQSHost,
mQSCustomizerController, mMediaHost,
mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
mController.init();
@@ -259,7 +259,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true);
when(mQSPanel.getDumpableTag()).thenReturn("QSPanelPortrait");
- mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
+ mController = new TestableQSPanelControllerBase(mQSPanel, mQSHost,
mQSCustomizerController, mMediaHost,
mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
mController.init();
@@ -291,7 +291,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
@Test
public void testRefreshAllTilesDoesntRefreshListeningTiles() {
- when(mQSTileHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
+ when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
mController.setTiles();
when(mQSTile.isListening()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
index 09156d6d6752..a0d8f98a4ad1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
@@ -9,7 +9,6 @@ import com.android.internal.logging.UiEventLogger
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
import com.android.systemui.media.controls.ui.MediaHost
import com.android.systemui.media.controls.ui.MediaHostState
import com.android.systemui.plugins.FalsingManager
@@ -41,7 +40,7 @@ class QSPanelControllerTest : SysuiTestCase() {
@Mock private lateinit var qsPanel: QSPanel
@Mock private lateinit var tunerService: TunerService
- @Mock private lateinit var qsTileHost: QSTileHost
+ @Mock private lateinit var qsHost: QSHost
@Mock private lateinit var qsCustomizerController: QSCustomizerController
@Mock private lateinit var qsTileRevealControllerFactory: QSTileRevealController.Factory
@Mock private lateinit var dumpManager: DumpManager
@@ -57,7 +56,6 @@ class QSPanelControllerTest : SysuiTestCase() {
@Mock private lateinit var tile: QSTile
@Mock private lateinit var otherTile: QSTile
@Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
- @Mock private lateinit var featureFlags: FeatureFlags
@Mock private lateinit var configuration: Configuration
@Mock private lateinit var pagedTileLayout: PagedTileLayout
@@ -81,7 +79,7 @@ class QSPanelControllerTest : SysuiTestCase() {
controller = QSPanelController(
qsPanel,
tunerService,
- qsTileHost,
+ qsHost,
qsCustomizerController,
/* usingMediaPlayer= */ true,
mediaHost,
@@ -93,8 +91,7 @@ class QSPanelControllerTest : SysuiTestCase() {
brightnessControllerFactory,
brightnessSliderFactory,
falsingManager,
- statusBarKeyguardViewManager,
- featureFlags
+ statusBarKeyguardViewManager
)
}
@@ -112,7 +109,7 @@ class QSPanelControllerTest : SysuiTestCase() {
@Test
fun testSetListeningDoesntRefreshListeningTiles() {
- whenever(qsTileHost.getTiles()).thenReturn(listOf(tile, otherTile))
+ whenever(qsHost.getTiles()).thenReturn(listOf(tile, otherTile))
controller.setTiles()
whenever(tile.isListening()).thenReturn(false)
whenever(otherTile.isListening()).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
index a8cfb256bc7c..93cebe2bcd16 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
@@ -165,26 +165,11 @@ class QSPanelTest : SysuiTestCase() {
}
@Test
- fun testTopPadding_notCombinedHeaders() {
- qsPanel.setUsingCombinedHeaders(false)
+ fun testTopPadding() {
val padding = 10
val paddingCombined = 100
context.orCreateTestableResources.addOverride(R.dimen.qs_panel_padding_top, padding)
- context.orCreateTestableResources.addOverride(
- R.dimen.qs_panel_padding_top_combined_headers, paddingCombined)
-
- qsPanel.updatePadding()
- assertThat(qsPanel.paddingTop).isEqualTo(padding)
- }
-
- @Test
- fun testTopPadding_combinedHeaders() {
- qsPanel.setUsingCombinedHeaders(true)
- val padding = 10
- val paddingCombined = 100
- context.orCreateTestableResources.addOverride(R.dimen.qs_panel_padding_top, padding)
- context.orCreateTestableResources.addOverride(
- R.dimen.qs_panel_padding_top_combined_headers, paddingCombined)
+ context.orCreateTestableResources.addOverride(R.dimen.qs_panel_padding_top, paddingCombined)
qsPanel.updatePadding()
assertThat(qsPanel.paddingTop).isEqualTo(paddingCombined)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index fb1a720b82f6..34d2b14d46a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -69,7 +69,6 @@ import com.android.systemui.settings.UserFileManager;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.FakeSharedPreferences;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -100,11 +99,9 @@ public class QSTileHostTest extends SysuiTestCase {
private static ComponentName CUSTOM_TILE =
ComponentName.unflattenFromString("TEST_PKG/.TEST_CLS");
private static final String CUSTOM_TILE_SPEC = CustomTile.toSpec(CUSTOM_TILE);
- private static final String SETTING = QSTileHost.TILES_SETTING;
+ private static final String SETTING = QSHost.TILES_SETTING;
@Mock
- private StatusBarIconController mIconController;
- @Mock
private QSFactory mDefaultFactory;
@Mock
private PluginManager mPluginManager;
@@ -167,7 +164,7 @@ public class QSTileHostTest extends SysuiTestCase {
mSecureSettings = new FakeSettings();
saveSetting("");
- mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mMainExecutor,
+ mQSTileHost = new TestQSTileHost(mContext, mDefaultFactory, mMainExecutor,
mPluginManager, mTunerService, mAutoTiles, mDumpManager, mCentralSurfaces,
mQSLogger, mUiEventLogger, mUserTracker, mSecureSettings, mCustomTileStatePersister,
mTileServiceRequestControllerBuilder, mTileLifecycleManagerFactory,
@@ -248,44 +245,44 @@ public class QSTileHostTest extends SysuiTestCase {
public void testRemoveWifiAndCellularWithoutInternet() {
saveSetting("wifi, spec1, cell, spec2");
- assertEquals("internet", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(1));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ assertEquals("internet", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec1", mQSTileHost.getSpecs().get(1));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(2));
}
@Test
public void testRemoveWifiAndCellularWithInternet() {
saveSetting("wifi, spec1, cell, spec2, internet");
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
- assertEquals("internet", mQSTileHost.mTileSpecs.get(2));
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(1));
+ assertEquals("internet", mQSTileHost.getSpecs().get(2));
}
@Test
public void testRemoveWifiWithoutInternet() {
saveSetting("spec1, wifi, spec2");
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("internet", mQSTileHost.mTileSpecs.get(1));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("internet", mQSTileHost.getSpecs().get(1));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(2));
}
@Test
public void testRemoveCellWithInternet() {
saveSetting("spec1, spec2, cell, internet");
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
- assertEquals("internet", mQSTileHost.mTileSpecs.get(2));
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(1));
+ assertEquals("internet", mQSTileHost.getSpecs().get(2));
}
@Test
public void testNoWifiNoCellularNoInternet() {
saveSetting("spec1,spec2");
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(1));
}
@Test
@@ -332,9 +329,9 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile("spec1");
- assertEquals(2, mQSTileHost.mTileSpecs.size());
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+ assertEquals(2, mQSTileHost.getSpecs().size());
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(1));
}
@Test
@@ -346,10 +343,10 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile("spec2", 1);
mMainExecutor.runAllReady();
- assertEquals(3, mQSTileHost.mTileSpecs.size());
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
- assertEquals("spec3", mQSTileHost.mTileSpecs.get(2));
+ assertEquals(3, mQSTileHost.getSpecs().size());
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(1));
+ assertEquals("spec3", mQSTileHost.getSpecs().get(2));
}
@Test
@@ -361,10 +358,10 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile("spec2", 100);
mMainExecutor.runAllReady();
- assertEquals(3, mQSTileHost.mTileSpecs.size());
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec3", mQSTileHost.mTileSpecs.get(1));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ assertEquals(3, mQSTileHost.getSpecs().size());
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec3", mQSTileHost.getSpecs().get(1));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(2));
}
@Test
@@ -376,10 +373,10 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile("spec2", QSTileHost.POSITION_AT_END);
mMainExecutor.runAllReady();
- assertEquals(3, mQSTileHost.mTileSpecs.size());
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec3", mQSTileHost.mTileSpecs.get(1));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ assertEquals(3, mQSTileHost.getSpecs().size());
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec3", mQSTileHost.getSpecs().get(1));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(2));
}
@Test
@@ -389,8 +386,8 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile(CUSTOM_TILE, /* end */ false);
mMainExecutor.runAllReady();
- assertEquals(1, mQSTileHost.mTileSpecs.size());
- assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(0));
+ assertEquals(1, mQSTileHost.getSpecs().size());
+ assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(0));
}
@Test
@@ -400,8 +397,8 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile(CUSTOM_TILE);
mMainExecutor.runAllReady();
- assertEquals(2, mQSTileHost.mTileSpecs.size());
- assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(0));
+ assertEquals(2, mQSTileHost.getSpecs().size());
+ assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(0));
}
@Test
@@ -411,8 +408,8 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile(CUSTOM_TILE, /* end */ false);
mMainExecutor.runAllReady();
- assertEquals(2, mQSTileHost.mTileSpecs.size());
- assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(0));
+ assertEquals(2, mQSTileHost.getSpecs().size());
+ assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(0));
}
@Test
@@ -422,8 +419,8 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile(CUSTOM_TILE, /* end */ true);
mMainExecutor.runAllReady();
- assertEquals(2, mQSTileHost.mTileSpecs.size());
- assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(1));
+ assertEquals(2, mQSTileHost.getSpecs().size());
+ assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(1));
}
@Test
@@ -478,7 +475,7 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.removeTiles(List.of("spec1", "spec2"));
mMainExecutor.runAllReady();
- assertEquals(List.of("spec3"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec3"), mQSTileHost.getSpecs());
}
@Test
@@ -488,7 +485,7 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.removeTile("spec3");
mMainExecutor.runAllReady();
- assertEquals(List.of("spec2"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec2"), mQSTileHost.getSpecs());
assertEquals("spec2", getSetting());
}
@@ -497,10 +494,10 @@ public class QSTileHostTest extends SysuiTestCase {
saveSetting("spec1,spec2");
mQSTileHost.addTile("spec3");
- assertEquals(List.of("spec1", "spec2"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1", "spec2"), mQSTileHost.getSpecs());
mMainExecutor.runAllReady();
- assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.getSpecs());
}
@Test
@@ -508,10 +505,10 @@ public class QSTileHostTest extends SysuiTestCase {
saveSetting("spec1,spec2");
mQSTileHost.removeTile("spec1");
- assertEquals(List.of("spec1", "spec2"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1", "spec2"), mQSTileHost.getSpecs());
mMainExecutor.runAllReady();
- assertEquals(List.of("spec2"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec2"), mQSTileHost.getSpecs());
}
@Test
@@ -519,10 +516,10 @@ public class QSTileHostTest extends SysuiTestCase {
saveSetting("spec1,spec2,spec3");
mQSTileHost.removeTiles(List.of("spec3", "spec1"));
- assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.getSpecs());
mMainExecutor.runAllReady();
- assertEquals(List.of("spec2"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec2"), mQSTileHost.getSpecs());
}
@Test
@@ -530,17 +527,17 @@ public class QSTileHostTest extends SysuiTestCase {
saveSetting("spec1," + CUSTOM_TILE_SPEC);
mQSTileHost.removeTileByUser(CUSTOM_TILE);
- assertEquals(List.of("spec1", CUSTOM_TILE_SPEC), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1", CUSTOM_TILE_SPEC), mQSTileHost.getSpecs());
mMainExecutor.runAllReady();
- assertEquals(List.of("spec1"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1"), mQSTileHost.getSpecs());
}
@Test
public void testNonValidTileNotStoredInSettings() {
saveSetting("spec1,not-valid");
- assertEquals(List.of("spec1"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1"), mQSTileHost.getSpecs());
assertEquals("spec1", getSetting());
}
@@ -548,14 +545,14 @@ public class QSTileHostTest extends SysuiTestCase {
public void testNotAvailableTileNotStoredInSettings() {
saveSetting("spec1,na");
- assertEquals(List.of("spec1"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1"), mQSTileHost.getSpecs());
assertEquals("spec1", getSetting());
}
@Test
public void testIsTileAdded_true() {
int user = mUserTracker.getUserId();
- getSharedPreferenecesForUser(user)
+ getSharedPreferencesForUser(user)
.edit()
.putBoolean(CUSTOM_TILE.flattenToString(), true)
.apply();
@@ -566,7 +563,7 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testIsTileAdded_false() {
int user = mUserTracker.getUserId();
- getSharedPreferenecesForUser(user)
+ getSharedPreferencesForUser(user)
.edit()
.putBoolean(CUSTOM_TILE.flattenToString(), false)
.apply();
@@ -597,7 +594,7 @@ public class QSTileHostTest extends SysuiTestCase {
int user = mUserTracker.getUserId();
mQSTileHost.setTileAdded(CUSTOM_TILE, user, true);
- assertTrue(getSharedPreferenecesForUser(user)
+ assertTrue(getSharedPreferencesForUser(user)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -606,7 +603,7 @@ public class QSTileHostTest extends SysuiTestCase {
int user = mUserTracker.getUserId();
mQSTileHost.setTileAdded(CUSTOM_TILE, user, false);
- assertFalse(getSharedPreferenecesForUser(user)
+ assertFalse(getSharedPreferencesForUser(user)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -615,7 +612,7 @@ public class QSTileHostTest extends SysuiTestCase {
int user = mUserTracker.getUserId();
mQSTileHost.setTileAdded(CUSTOM_TILE, user, true);
- assertFalse(getSharedPreferenecesForUser(user + 1)
+ assertFalse(getSharedPreferencesForUser(user + 1)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -627,8 +624,8 @@ public class QSTileHostTest extends SysuiTestCase {
// This will be done by TileServiceManager
mQSTileHost.setTileAdded(CUSTOM_TILE, user, true);
- mQSTileHost.changeTilesByUser(mQSTileHost.mTileSpecs, List.of("spec1"));
- assertFalse(getSharedPreferenecesForUser(user)
+ mQSTileHost.changeTilesByUser(mQSTileHost.getSpecs(), List.of("spec1"));
+ assertFalse(getSharedPreferencesForUser(user)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -642,7 +639,7 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.removeTileByUser(CUSTOM_TILE);
mMainExecutor.runAllReady();
- assertFalse(getSharedPreferenecesForUser(user)
+ assertFalse(getSharedPreferencesForUser(user)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -656,7 +653,7 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.removeTile(CUSTOM_TILE_SPEC);
mMainExecutor.runAllReady();
- assertFalse(getSharedPreferenecesForUser(user)
+ assertFalse(getSharedPreferencesForUser(user)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -681,12 +678,12 @@ public class QSTileHostTest extends SysuiTestCase {
assertEquals(CUSTOM_TILE.getClassName(), proto.tiles[1].getComponentName().className);
}
- private SharedPreferences getSharedPreferenecesForUser(int user) {
+ private SharedPreferences getSharedPreferencesForUser(int user) {
return mUserFileManager.getSharedPreferences(QSTileHost.TILES, 0, user);
}
private class TestQSTileHost extends QSTileHost {
- TestQSTileHost(Context context, StatusBarIconController iconController,
+ TestQSTileHost(Context context,
QSFactory defaultFactory, Executor mainExecutor,
PluginManager pluginManager, TunerService tunerService,
Provider<AutoTileManager> autoTiles, DumpManager dumpManager,
@@ -696,7 +693,7 @@ public class QSTileHostTest extends SysuiTestCase {
TileServiceRequestController.Builder tileServiceRequestControllerBuilder,
TileLifecycleManager.Factory tileLifecycleManagerFactory,
UserFileManager userFileManager) {
- super(context, iconController, defaultFactory, mainExecutor, pluginManager,
+ super(context, defaultFactory, mainExecutor, pluginManager,
tunerService, autoTiles, dumpManager, Optional.of(centralSurfaces), qsLogger,
uiEventLogger, userTracker, secureSettings, customTileStatePersister,
tileServiceRequestControllerBuilder, tileLifecycleManagerFactory,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index f53e997a331c..71ea831e0f92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -50,7 +50,7 @@ import org.mockito.MockitoAnnotations
class QuickQSPanelControllerTest : SysuiTestCase() {
@Mock private lateinit var quickQSPanel: QuickQSPanel
- @Mock private lateinit var qsTileHost: QSTileHost
+ @Mock private lateinit var qsHost: QSHost
@Mock private lateinit var qsCustomizerController: QSCustomizerController
@Mock private lateinit var mediaHost: MediaHost
@Mock private lateinit var metricsLogger: MetricsLogger
@@ -75,12 +75,12 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
whenever(quickQSPanel.isAttachedToWindow).thenReturn(true)
whenever(quickQSPanel.dumpableTag).thenReturn("")
whenever(quickQSPanel.resources).thenReturn(mContext.resources)
- whenever(qsTileHost.createTileView(any(), any(), anyBoolean())).thenReturn(tileView)
+ whenever(qsHost.createTileView(any(), any(), anyBoolean())).thenReturn(tileView)
controller =
TestQuickQSPanelController(
quickQSPanel,
- qsTileHost,
+ qsHost,
qsCustomizerController,
/* usingMediaPlayer = */ false,
mediaHost,
@@ -102,7 +102,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
fun testTileSublistWithFewerTiles_noCrash() {
whenever(quickQSPanel.numQuickTiles).thenReturn(3)
- whenever(qsTileHost.tiles).thenReturn(listOf(tile, tile))
+ whenever(qsHost.tiles).thenReturn(listOf(tile, tile))
controller.setTiles()
}
@@ -111,7 +111,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
fun testTileSublistWithTooManyTiles() {
val limit = 3
whenever(quickQSPanel.numQuickTiles).thenReturn(limit)
- whenever(qsTileHost.tiles).thenReturn(listOf(tile, tile, tile, tile))
+ whenever(qsHost.tiles).thenReturn(listOf(tile, tile, tile, tile))
controller.setTiles()
@@ -147,7 +147,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
class TestQuickQSPanelController(
view: QuickQSPanel,
- qsTileHost: QSTileHost,
+ qsHost: QSHost,
qsCustomizerController: QSCustomizerController,
usingMediaPlayer: Boolean,
mediaHost: MediaHost,
@@ -159,7 +159,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
) :
QuickQSPanelController(
view,
- qsTileHost,
+ qsHost,
qsCustomizerController,
usingMediaPlayer,
mediaHost,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
index 39d89bf99af2..555484cc17f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
@@ -18,37 +18,16 @@ package com.android.systemui.qs
import android.content.Context
import android.testing.AndroidTestingRunner
-import android.view.View
import androidx.test.filters.SmallTest
-import com.android.systemui.R
import com.android.systemui.SysuiTestCase
-import com.android.systemui.battery.BatteryMeterViewController
-import com.android.systemui.colorextraction.SysuiColorExtractor
-import com.android.systemui.demomode.DemoModeController
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.qs.carrier.QSCarrierGroup
-import com.android.systemui.qs.carrier.QSCarrierGroupController
-import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
-import com.android.systemui.statusbar.phone.StatusBarIconController
-import com.android.systemui.statusbar.phone.StatusIconContainer
-import com.android.systemui.statusbar.policy.Clock
-import com.android.systemui.statusbar.policy.VariableDateView
-import com.android.systemui.statusbar.policy.VariableDateViewController
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
-import com.android.systemui.util.mockito.capture
-import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Answers
-import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
-import org.mockito.Mockito.anyBoolean
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@SmallTest
@@ -58,78 +37,21 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
@Mock
private lateinit var view: QuickStatusBarHeader
@Mock
- private lateinit var privacyIconsController: HeaderPrivacyIconsController
- @Mock
- private lateinit var statusBarIconController: StatusBarIconController
- @Mock
- private lateinit var demoModeController: DemoModeController
- @Mock
private lateinit var quickQSPanelController: QuickQSPanelController
- @Mock(answer = Answers.RETURNS_SELF)
- private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
- @Mock
- private lateinit var qsCarrierGroupController: QSCarrierGroupController
- @Mock
- private lateinit var colorExtractor: SysuiColorExtractor
- @Mock
- private lateinit var iconContainer: StatusIconContainer
- @Mock
- private lateinit var qsCarrierGroup: QSCarrierGroup
- @Mock
- private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory
- @Mock
- private lateinit var variableDateViewController: VariableDateViewController
- @Mock
- private lateinit var batteryMeterViewController: BatteryMeterViewController
- @Mock
- private lateinit var clock: Clock
- @Mock
- private lateinit var variableDateView: VariableDateView
- @Mock
- private lateinit var mockView: View
+
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private lateinit var context: Context
- @Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
- private lateinit var insetsProvider: StatusBarContentInsetsProvider
- @Mock
- private lateinit var iconManagerFactory: StatusBarIconController.TintedIconManager.Factory
- @Mock
- private lateinit var iconManager: StatusBarIconController.TintedIconManager
-
- private val qsExpansionPathInterpolator = QSExpansionPathInterpolator()
private lateinit var controller: QuickStatusBarHeaderController
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- stubViews()
- `when`(iconContainer.context).thenReturn(context)
- `when`(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
- `when`(variableDateViewControllerFactory.create(any()))
- .thenReturn(variableDateViewController)
- `when`(iconManagerFactory.create(any(), any())).thenReturn(iconManager)
`when`(view.resources).thenReturn(mContext.resources)
`when`(view.isAttachedToWindow).thenReturn(true)
`when`(view.context).thenReturn(context)
- controller = QuickStatusBarHeaderController(
- view,
- privacyIconsController,
- statusBarIconController,
- demoModeController,
- quickQSPanelController,
- qsCarrierGroupControllerBuilder,
- colorExtractor,
- qsExpansionPathInterpolator,
- featureFlags,
- variableDateViewControllerFactory,
- batteryMeterViewController,
- insetsProvider,
- iconManagerFactory,
- )
+ controller = QuickStatusBarHeaderController(view, quickQSPanelController)
}
@After
@@ -138,74 +60,11 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
}
@Test
- fun testClockNotClickable() {
- assertThat(clock.isClickable).isFalse()
- }
-
- @Test
- fun testSingleCarrierListenerAttachedOnInit() {
- controller.init()
-
- verify(qsCarrierGroupController).setOnSingleCarrierChangedListener(any())
- }
-
- @Test
- fun testSingleCarrierSetOnViewOnInit_false() {
- `when`(qsCarrierGroupController.isSingleCarrier).thenReturn(false)
- controller.init()
-
- verify(view).setIsSingleCarrier(false)
- }
-
- @Test
- fun testSingleCarrierSetOnViewOnInit_true() {
- `when`(qsCarrierGroupController.isSingleCarrier).thenReturn(true)
- controller.init()
-
- verify(view).setIsSingleCarrier(true)
- }
-
- @Test
- fun testRSSISlot_notCombined() {
- controller.init()
-
- val captor = argumentCaptor<List<String>>()
- verify(view).onAttach(any(), any(), capture(captor), any(), anyBoolean())
-
- assertThat(captor.value).containsExactly(
- mContext.getString(com.android.internal.R.string.status_bar_mobile)
- )
- }
-
- @Test
- fun testSingleCarrierCallback() {
- controller.init()
- reset(view)
-
- val captor = argumentCaptor<QSCarrierGroupController.OnSingleCarrierChangedListener>()
- verify(qsCarrierGroupController).setOnSingleCarrierChangedListener(capture(captor))
-
- captor.value.onSingleCarrierChanged(true)
- verify(view).setIsSingleCarrier(true)
-
- captor.value.onSingleCarrierChanged(false)
- verify(view).setIsSingleCarrier(false)
- }
-
- @Test
- fun testAlarmIconIgnored() {
- controller.init()
-
- verify(iconContainer).addIgnoredSlot(
- mContext.getString(com.android.internal.R.string.status_bar_alarm_clock))
- }
+ fun testListeningStatus() {
+ controller.setListening(true)
+ verify(quickQSPanelController).setListening(true)
- private fun stubViews() {
- `when`(view.findViewById<View>(anyInt())).thenReturn(mockView)
- `when`(view.findViewById<QSCarrierGroup>(R.id.carrier_group)).thenReturn(qsCarrierGroup)
- `when`(view.findViewById<StatusIconContainer>(R.id.statusIcons)).thenReturn(iconContainer)
- `when`(view.findViewById<Clock>(R.id.clock)).thenReturn(clock)
- `when`(view.requireViewById<VariableDateView>(R.id.date)).thenReturn(variableDateView)
- `when`(view.requireViewById<VariableDateView>(R.id.date_clock)).thenReturn(variableDateView)
+ controller.setListening(false)
+ verify(quickQSPanelController).setListening(false)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
index d42cbe3b698a..c041cb6d0b1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
@@ -25,7 +25,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import org.junit.Before;
import org.junit.Test;
@@ -42,19 +42,19 @@ public class TileAdapterTest extends SysuiTestCase {
private TileAdapter mTileAdapter;
@Mock
- private QSTileHost mQSTileHost;
+ private QSHost mQSHost;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
TestableLooper.get(this).runWithLooper(() -> mTileAdapter =
- new TileAdapter(mContext, mQSTileHost, new UiEventLoggerFake()));
+ new TileAdapter(mContext, mQSHost, new UiEventLoggerFake()));
}
@Test
public void testResetNotifiesHost() {
mTileAdapter.resetTileSpecs(Collections.emptyList());
- verify(mQSTileHost).changeTilesByUser(any(), any());
+ verify(mQSHost).changeTilesByUser(any(), any());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index 040af70f2077..78a02584c40a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -55,7 +55,7 @@ import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -102,7 +102,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
@Mock
private TileQueryHelper.TileStateListener mListener;
@Mock
- private QSTileHost mQSTileHost;
+ private QSHost mQSHost;
@Mock
private PackageManager mPackageManager;
@Mock
@@ -131,7 +131,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
return null;
}
}
- ).when(mQSTileHost).createTile(anyString());
+ ).when(mQSHost).createTile(anyString());
FakeSystemClock clock = new FakeSystemClock();
mMainExecutor = new FakeExecutor(clock);
mBgExecutor = new FakeExecutor(clock);
@@ -147,7 +147,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
@Test
public void testIsFinished_trueAfterQuerying() {
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -156,7 +156,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
@Test
public void testQueryTiles_callsListenerTwice() {
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -170,7 +170,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
return null;
}).when(mListener).onTilesChanged(any());
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -184,7 +184,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
STOCK_TILES);
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -204,7 +204,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
STOCK_TILES);
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -224,7 +224,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
STOCK_TILES);
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -240,9 +240,9 @@ public class TileQueryHelperTest extends SysuiTestCase {
public void testCustomTileNotCreated() {
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES,
CUSTOM_TILE);
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
- verify(mQSTileHost, never()).createTile(CUSTOM_TILE);
+ verify(mQSHost, never()).createTile(CUSTOM_TILE);
}
@Test
@@ -264,7 +264,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
"");
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
@@ -278,7 +278,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, null);
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
STOCK_TILES);
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
}
@Test
@@ -286,12 +286,12 @@ public class TileQueryHelperTest extends SysuiTestCase {
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, null);
QSTile t = mock(QSTile.class);
- when(mQSTileHost.createTile("hotspot")).thenReturn(t);
+ when(mQSHost.createTile("hotspot")).thenReturn(t);
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
"hotspot");
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
InOrder verifier = inOrder(t);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
index 8644b5ea18ae..5be95d6f6255 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
@@ -57,6 +57,7 @@ import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
@@ -351,4 +352,44 @@ class CustomTileTest : SysuiTestCase() {
.startPendingIntentDismissingKeyguard(
eq(pi), nullable(), nullable<ActivityLaunchAnimator.Controller>())
}
+
+ @Test
+ fun testActiveTileListensOnceAfterCreated() {
+ `when`(tileServiceManager.isActiveTile).thenReturn(true)
+
+ val tile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
+ tile.initialize()
+ tile.postStale()
+ testableLooper.processAllMessages()
+
+ verify(tileServiceManager).setBindRequested(true)
+ verify(tileService).onStartListening()
+ }
+
+ @Test
+ fun testActiveTileDoesntListenAfterFirstTime() {
+ `when`(tileServiceManager.isActiveTile).thenReturn(true)
+
+ val tile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
+ tile.initialize()
+ // Make sure we have an icon in the tile because we don't have a default icon
+ // This should not be overridden by the retrieved tile that has null icon.
+ tile.qsTile.icon = mock(Icon::class.java)
+ `when`(tile.qsTile.icon.loadDrawable(any(Context::class.java)))
+ .thenReturn(mock(Drawable::class.java))
+
+ tile.postStale()
+ testableLooper.processAllMessages()
+
+ // postStale will set it to not listening after it's done
+ verify(tileService).onStopListening()
+
+ clearInvocations(tileServiceManager, tileService)
+
+ tile.setListening(Any(), true)
+ testableLooper.processAllMessages()
+
+ verify(tileServiceManager, never()).setBindRequested(true)
+ verify(tileService, never()).onStartListening()
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
index 8aa625a7ea20..46af89e00db4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
@@ -39,7 +39,7 @@ import android.test.suitebuilder.annotation.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import org.junit.After;
@@ -61,7 +61,7 @@ public class TileServiceManagerTest extends SysuiTestCase {
@Mock
private UserTracker mUserTracker;
@Mock
- private QSTileHost mQSTileHost;
+ private QSHost mQSHost;
@Mock
private Context mMockContext;
@@ -80,7 +80,7 @@ public class TileServiceManagerTest extends SysuiTestCase {
when(mUserTracker.getUserHandle()).thenReturn(UserHandle.SYSTEM);
when(mTileServices.getContext()).thenReturn(mMockContext);
- when(mTileServices.getHost()).thenReturn(mQSTileHost);
+ when(mTileServices.getHost()).thenReturn(mQSHost);
when(mTileLifecycle.getUserId()).thenAnswer(invocation -> mUserTracker.getUserId());
when(mTileLifecycle.isActiveTile()).thenReturn(false);
@@ -98,28 +98,28 @@ public class TileServiceManagerTest extends SysuiTestCase {
@Test
public void testSetTileAddedIfNotAdded() {
- when(mQSTileHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(false);
+ when(mQSHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(false);
mTileServiceManager.startLifecycleManagerAndAddTile();
- verify(mQSTileHost).setTileAdded(mComponentName, mUserTracker.getUserId(), true);
+ verify(mQSHost).setTileAdded(mComponentName, mUserTracker.getUserId(), true);
}
@Test
public void testNotSetTileAddedIfAdded() {
- when(mQSTileHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(true);
+ when(mQSHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(true);
mTileServiceManager.startLifecycleManagerAndAddTile();
- verify(mQSTileHost, never()).setTileAdded(eq(mComponentName), anyInt(), eq(true));
+ verify(mQSHost, never()).setTileAdded(eq(mComponentName), anyInt(), eq(true));
}
@Test
public void testSetTileAddedCorrectUser() {
int user = 10;
when(mUserTracker.getUserId()).thenReturn(user);
- when(mQSTileHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(false);
+ when(mQSHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(false);
mTileServiceManager.startLifecycleManagerAndAddTile();
- verify(mQSTileHost).setTileAdded(mComponentName, user, true);
+ verify(mQSHost).setTileAdded(mComponentName, user, true);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
index bdfbca47e569..ccfb5cf8959a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
@@ -27,27 +27,27 @@ import com.android.internal.logging.InstanceId
import com.android.internal.statusbar.IAddTileResultCallback
import com.android.systemui.InstanceIdSequenceFake
import com.android.systemui.SysuiTestCase
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.google.common.truth.Truth.assertThat
+import java.util.function.Consumer
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyBoolean
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.anyString
import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
-import java.util.function.Consumer
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -62,7 +62,7 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
@Mock
private lateinit var tileRequestDialog: TileRequestDialog
@Mock
- private lateinit var qsTileHost: QSTileHost
+ private lateinit var qsHost: QSHost
@Mock
private lateinit var commandRegistry: CommandRegistry
@Mock
@@ -82,10 +82,10 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
`when`(logger.newInstanceId()).thenReturn(instanceIdSequence.newInstanceId())
// Tile not present by default
- `when`(qsTileHost.indexOf(anyString())).thenReturn(-1)
+ `when`(qsHost.indexOf(anyString())).thenReturn(-1)
controller = TileServiceRequestController(
- qsTileHost,
+ qsHost,
commandQueue,
commandRegistry,
logger
@@ -107,18 +107,18 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
@Test
fun tileAlreadyAdded_correctResult() {
- `when`(qsTileHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
+ `when`(qsHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
val callback = Callback()
controller.requestTileAdd(TEST_COMPONENT, TEST_APP_NAME, TEST_LABEL, icon, callback)
assertThat(callback.lastAccepted).isEqualTo(TileServiceRequestController.TILE_ALREADY_ADDED)
- verify(qsTileHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
+ verify(qsHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
}
@Test
fun tileAlreadyAdded_logged() {
- `when`(qsTileHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
+ `when`(qsHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
controller.requestTileAdd(TEST_COMPONENT, TEST_APP_NAME, TEST_LABEL, icon) {}
@@ -157,7 +157,7 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
cancelListenerCaptor.value.onCancel(tileRequestDialog)
assertThat(callback.lastAccepted).isEqualTo(TileServiceRequestController.DISMISSED)
- verify(qsTileHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
+ verify(qsHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
}
@Test
@@ -191,7 +191,7 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
clickListenerCaptor.value.onClick(tileRequestDialog, DialogInterface.BUTTON_POSITIVE)
assertThat(callback.lastAccepted).isEqualTo(TileServiceRequestController.ADD_TILE)
- verify(qsTileHost).addTile(TEST_COMPONENT, /* end */ true)
+ verify(qsHost).addTile(TEST_COMPONENT, /* end */ true)
}
@Test
@@ -225,7 +225,7 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
clickListenerCaptor.value.onClick(tileRequestDialog, DialogInterface.BUTTON_NEGATIVE)
assertThat(callback.lastAccepted).isEqualTo(TileServiceRequestController.DONT_ADD_TILE)
- verify(qsTileHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
+ verify(qsHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
}
@Test
@@ -266,7 +266,7 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
@Test
fun commandQueueCallback_callbackCalled() {
- `when`(qsTileHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
+ `when`(qsHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
val captor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
verify(commandQueue, atLeastOnce()).addCallback(capture(captor))
val c = Callback()
@@ -365,4 +365,4 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
accept(r)
}
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 172c87f0c50b..64e9a3e58bd6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -30,7 +30,6 @@ import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.quicksettings.IQSTileService;
@@ -39,24 +38,13 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
-import com.android.internal.logging.UiEventLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.qs.QSTileHost;
-import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.qs.tileimpl.QSFactoryImpl;
-import com.android.systemui.settings.UserFileManager;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.AutoTileManager;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Assert;
@@ -68,8 +56,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
-import java.util.Optional;
-import java.util.concurrent.Executor;
import javax.inject.Provider;
@@ -92,26 +78,8 @@ public class TileServicesTest extends SysuiTestCase {
@Mock
private StatusBarIconController mStatusBarIconController;
@Mock
- private QSFactoryImpl mQSFactory;
- @Mock
- private PluginManager mPluginManager;
- @Mock
- private TunerService mTunerService;
- @Mock
- private AutoTileManager mAutoTileManager;
- @Mock
- private DumpManager mDumpManager;
- @Mock
- private CentralSurfaces mCentralSurfaces;
- @Mock
- private QSLogger mQSLogger;
- @Mock
- private UiEventLogger mUiEventLogger;
- @Mock
private UserTracker mUserTracker;
@Mock
- private SecureSettings mSecureSettings;
- @Mock
private TileServiceRequestController.Builder mTileServiceRequestControllerBuilder;
@Mock
private TileServiceRequestController mTileServiceRequestController;
@@ -122,12 +90,11 @@ public class TileServicesTest extends SysuiTestCase {
@Mock
private TileLifecycleManager mTileLifecycleManager;
@Mock
- private UserFileManager mUserFileManager;
+ private QSHost mQSHost;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mDependency.injectMockDependency(BluetoothController.class);
mManagers = new ArrayList<>();
mTestableLooper = TestableLooper.get(this);
@@ -135,34 +102,16 @@ public class TileServicesTest extends SysuiTestCase {
.thenReturn(mTileServiceRequestController);
when(mTileLifecycleManagerFactory.create(any(Intent.class), any(UserHandle.class)))
.thenReturn(mTileLifecycleManager);
+ when(mQSHost.getContext()).thenReturn(mContext);
Provider<Handler> provider = () -> new Handler(mTestableLooper.getLooper());
- Executor executor = new HandlerExecutor(provider.get());
-
- QSTileHost host = new QSTileHost(mContext,
- mStatusBarIconController,
- mQSFactory,
- executor,
- mPluginManager,
- mTunerService,
- () -> mAutoTileManager,
- mDumpManager,
- Optional.of(mCentralSurfaces),
- mQSLogger,
- mUiEventLogger,
- mUserTracker,
- mSecureSettings,
- mock(CustomTileStatePersister.class),
- mTileServiceRequestControllerBuilder,
- mTileLifecycleManagerFactory,
- mUserFileManager);
- mTileService = new TestTileServices(host, provider, mBroadcastDispatcher,
- mUserTracker, mKeyguardStateController, mCommandQueue);
+
+ mTileService = new TestTileServices(mQSHost, provider, mBroadcastDispatcher,
+ mUserTracker, mKeyguardStateController, mCommandQueue, mStatusBarIconController);
}
@After
public void tearDown() throws Exception {
- mTileService.getHost().destroy();
mTileService.destroy();
TestableLooper.get(this).processAllMessages();
}
@@ -274,11 +223,12 @@ public class TileServicesTest extends SysuiTestCase {
}
private class TestTileServices extends TileServices {
- TestTileServices(QSTileHost host, Provider<Handler> handlerProvider,
+ TestTileServices(QSHost host, Provider<Handler> handlerProvider,
BroadcastDispatcher broadcastDispatcher, UserTracker userTracker,
- KeyguardStateController keyguardStateController, CommandQueue commandQueue) {
+ KeyguardStateController keyguardStateController, CommandQueue commandQueue,
+ StatusBarIconController statusBarIconController) {
super(host, handlerProvider, broadcastDispatcher, userTracker, keyguardStateController,
- commandQueue);
+ commandQueue, statusBarIconController);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index ba49f3fa66ee..36549fb826ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -69,7 +69,6 @@ import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSEvent;
import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.statusbar.StatusBarState;
@@ -97,7 +96,7 @@ public class QSTileImplTest extends SysuiTestCase {
private TestableLooper mTestableLooper;
private TileImpl mTile;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
private final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
index 030c59faa696..5e0190b65a12 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
@@ -38,6 +38,7 @@ import com.android.systemui.settings.UserTracker
import com.android.systemui.util.settings.GlobalSettings
import com.google.common.truth.Truth.assertThat
import dagger.Lazy
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -94,6 +95,12 @@ class AirplaneModeTileTest : SysuiTestCase() {
mUserTracker)
}
+ @After
+ fun tearDown() {
+ mTile.destroy()
+ mTestableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenDisabled_showsOffState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
index b4a662974d22..f1e3e8a71398 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
@@ -21,6 +21,7 @@ import com.android.systemui.statusbar.policy.NextAlarmController
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -88,6 +89,12 @@ class AlarmTileTest : SysuiTestCase() {
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testAvailable() {
assertThat(tile.isAvailable).isTrue()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
index 95e7ad9fad4d..a5c0004afe02 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
@@ -37,6 +37,7 @@ import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.util.settings.SecureSettings
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
@@ -103,6 +104,12 @@ class BatterySaverTileTest : SysuiTestCase() {
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testSettingWithCorrectUser() {
assertEquals(USER, tile.mSetting.currentUser)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
index d65901777a73..75fd0000e0e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
@@ -17,11 +17,12 @@ import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.BluetoothController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -40,7 +41,7 @@ class BluetoothTileTest : SysuiTestCase() {
@Mock
private lateinit var qsLogger: QSLogger
@Mock
- private lateinit var qsHost: QSTileHost
+ private lateinit var qsHost: QSHost
@Mock
private lateinit var metricsLogger: MetricsLogger
private val falsingManager = FalsingManagerFake()
@@ -79,6 +80,12 @@ class BluetoothTileTest : SysuiTestCase() {
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testRestrictionChecked() {
tile.refreshState()
@@ -135,7 +142,7 @@ class BluetoothTileTest : SysuiTestCase() {
}
private class FakeBluetoothTile(
- qsTileHost: QSTileHost,
+ qsHost: QSHost,
backgroundLooper: Looper,
mainHandler: Handler,
falsingManager: FalsingManager,
@@ -145,7 +152,7 @@ class BluetoothTileTest : SysuiTestCase() {
qsLogger: QSLogger,
bluetoothController: BluetoothController
) : BluetoothTile(
- qsTileHost,
+ qsHost,
backgroundLooper,
mainHandler,
falsingManager,
@@ -187,4 +194,4 @@ class BluetoothTileTest : SysuiTestCase() {
`when`(bluetoothController.isBluetoothConnected).thenReturn(false)
`when`(bluetoothController.isBluetoothConnecting).thenReturn(true)
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
index cfbb82f5f338..41938541124a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
@@ -35,6 +35,7 @@ import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -90,6 +91,12 @@ class CameraToggleTileTest : SysuiTestCase() {
keyguardStateController)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenCameraAccessEnabled_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
index b40a20c27820..64fd09d5f5d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -42,7 +42,7 @@ import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.statusbar.connectivity.IconState;
import com.android.systemui.statusbar.connectivity.NetworkController;
@@ -53,6 +53,7 @@ import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -78,7 +79,7 @@ public class CastTileTest extends SysuiTestCase {
@Mock
private NetworkController mNetworkController;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
SignalCallback mSignalCallback;
@Mock
@@ -141,6 +142,12 @@ public class CastTileTest extends SysuiTestCase {
mHotspotCallback = hotspotCallbackArgumentCaptor.getValue();
}
+ @After
+ public void tearDown() {
+ mCastTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
// -------------------------------------------------
// All these tests for enabled/disabled wifi have hotspot not enabled
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
index debe41c756bd..13c30e9ea9ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
@@ -37,12 +37,13 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -56,7 +57,7 @@ import org.mockito.MockitoAnnotations;
public class ColorCorrectionTileTest extends SysuiTestCase {
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -101,6 +102,12 @@ public class ColorCorrectionTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void longClick_expectedAction() {
final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
index 3fd25019e2a5..ff27e0255aa3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
@@ -39,13 +39,14 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -61,7 +62,7 @@ public class ColorInversionTileTest extends SysuiTestCase {
private static final Integer COLOR_INVERSION_ENABLED = 1;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -106,6 +107,12 @@ public class ColorInversionTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void longClick_expectedAction() {
final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
index ce62f2d1cf36..b048643aba84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
@@ -34,6 +34,7 @@ import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.DataSaverController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -84,6 +85,12 @@ class DataSaverTileTest : SysuiTestCase() {
)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenDataSaverEnabled_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index e0b3125fd62a..b51c378f6b6b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -67,6 +67,7 @@ import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
import java.util.Optional
+import org.junit.After
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -129,6 +130,12 @@ class DeviceControlsTileTest : SysuiTestCase() {
tile = createTile()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
private fun setupControlsComponent() {
`when`(controlsComponent.getControlsController()).thenAnswer {
if (featureEnabled) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
index ce5edb147d87..6c0904eb9bfd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
@@ -136,7 +136,8 @@ class DndTileTest : SysuiTestCase() {
@After
fun tearDown() {
- tile.handleSetListening(false)
+ tile.destroy()
+ testableLooper.processAllMessages()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
index a13bece4b489..13e4702d9db2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
@@ -47,13 +47,14 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -69,7 +70,7 @@ public class DreamTileTest extends SysuiTestCase {
@Mock
private ActivityStarter mActivityStarter;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -112,6 +113,12 @@ public class DreamTileTest extends SysuiTestCase {
mTile.initialize();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNotAvailable() throws RemoteException {
// Should not be available if screensaver is disabled
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
index d0f851bded75..692a64422a7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
@@ -13,11 +13,12 @@ import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.FlashlightController
import com.google.common.truth.Truth
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -34,7 +35,7 @@ class FlashlightTileTest : SysuiTestCase() {
@Mock private lateinit var qsLogger: QSLogger
- @Mock private lateinit var qsHost: QSTileHost
+ @Mock private lateinit var qsHost: QSHost
@Mock private lateinit var metricsLogger: MetricsLogger
@@ -71,6 +72,12 @@ class FlashlightTileTest : SysuiTestCase() {
)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenFlashlightEnabled_isOnState() {
Mockito.`when`(flashlightController.isAvailable).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
index 257d42a83ba4..1dd05c7b137b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
@@ -36,6 +36,7 @@ import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -87,6 +88,12 @@ class FontScalingTileTest : SysuiTestCase() {
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ fontScalingTile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun isAvailable_whenFlagIsFalse_returnsFalse() {
featureFlags.set(Flags.ENABLE_FONT_SCALING_TILE, false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
index 451e9119f297..959e750ac5f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
@@ -37,12 +37,13 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.HotspotController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -60,7 +61,7 @@ public class HotspotTileTest extends SysuiTestCase {
@Rule
public MockitoRule mRule = MockitoJUnit.rule();
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private HotspotController mHotspotController;
@Mock
@@ -94,6 +95,12 @@ public class HotspotTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void handleUpdateState_wifiTetheringIsAllowed_stateIsNotUnavailable() {
MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
index addca9d28d1a..adfd7f71e8f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
@@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-
import android.os.Handler;
import android.service.quicksettings.Tile;
import android.testing.AndroidTestingRunner;
@@ -35,7 +34,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.qs.tiles.dialog.InternetDialogFactory;
@@ -44,6 +43,7 @@ import com.android.systemui.statusbar.connectivity.IconState;
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.WifiIndicators;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -56,7 +56,7 @@ import org.mockito.MockitoAnnotations;
public class InternetTileTest extends SysuiTestCase {
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private NetworkController mNetworkController;
@Mock
@@ -92,6 +92,12 @@ public class InternetTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void setConnectivityStatus_defaultNetworkNotExists_updateTile() {
mTile.mSignalCallback.setConnectivityStatus(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
index d2bbc8cfac39..33921c7c84b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
@@ -29,12 +29,13 @@ import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.statusbar.policy.LocationController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -52,7 +53,7 @@ class LocationTileTest : SysuiTestCase() {
@Mock
private lateinit var qsLogger: QSLogger
@Mock
- private lateinit var qsHost: QSTileHost
+ private lateinit var qsHost: QSHost
@Mock
private lateinit var metricsLogger: MetricsLogger
private val falsingManager = FalsingManagerFake()
@@ -88,6 +89,12 @@ class LocationTileTest : SysuiTestCase() {
keyguardStateController)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenDisabled_isOffState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
index 1ab601ce3ebe..e2f64b2cc226 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
@@ -35,6 +35,7 @@ import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -90,6 +91,12 @@ class MicrophoneToggleTileTest : SysuiTestCase() {
keyguardStateController)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenMicrophoneAccessEnabled_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
index cfd37358dcff..c7dae83e2056 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
@@ -36,9 +36,10 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -60,7 +61,7 @@ public class NfcTileTest extends SysuiTestCase {
@Mock
private ActivityStarter mActivityStarter;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -97,6 +98,12 @@ public class NfcTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mNfcTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testIsAvailable_stockWithoutNfc_returnsFalse() {
when(mMockContext.getString(R.string.quick_settings_tiles_stock)).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
index 188c3a3d9e42..04af69c84cf8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
@@ -37,6 +37,7 @@ import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.LocationController
import com.google.common.truth.Truth
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -49,32 +50,23 @@ import org.mockito.MockitoAnnotations
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
class NightDisplayTileTest : SysuiTestCase() {
- @Mock
- private lateinit var mHost: QSHost
+ @Mock private lateinit var mHost: QSHost
- @Mock
- private lateinit var mMetricsLogger: MetricsLogger
+ @Mock private lateinit var mMetricsLogger: MetricsLogger
- @Mock
- private lateinit var mStatusBarStateController: StatusBarStateController
+ @Mock private lateinit var mStatusBarStateController: StatusBarStateController
- @Mock
- private lateinit var mActivityStarter: ActivityStarter
+ @Mock private lateinit var mActivityStarter: ActivityStarter
- @Mock
- private lateinit var mQsLogger: QSLogger
+ @Mock private lateinit var mQsLogger: QSLogger
- @Mock
- private lateinit var mLocationController: LocationController
+ @Mock private lateinit var mLocationController: LocationController
- @Mock
- private lateinit var mColorDisplayManager: ColorDisplayManager
+ @Mock private lateinit var mColorDisplayManager: ColorDisplayManager
- @Mock
- private lateinit var mNightDisplayListenerBuilder: NightDisplayListenerModule.Builder
+ @Mock private lateinit var mNightDisplayListenerBuilder: NightDisplayListenerModule.Builder
- @Mock
- private lateinit var mNightDisplayListener: NightDisplayListener
+ @Mock private lateinit var mNightDisplayListener: NightDisplayListener
private lateinit var mTestableLooper: TestableLooper
private lateinit var mTile: NightDisplayTile
@@ -88,24 +80,30 @@ class NightDisplayTileTest : SysuiTestCase() {
whenever(mHost.context).thenReturn(mContext)
whenever(mHost.uiEventLogger).thenReturn(mUiEventLogger)
whenever(mHost.userContext).thenReturn(mContext)
- whenever(mNightDisplayListenerBuilder.setUser(anyInt())).thenReturn(
- mNightDisplayListenerBuilder
- )
+ whenever(mNightDisplayListenerBuilder.setUser(anyInt()))
+ .thenReturn(mNightDisplayListenerBuilder)
whenever(mNightDisplayListenerBuilder.build()).thenReturn(mNightDisplayListener)
- mTile = NightDisplayTile(
- mHost,
- mTestableLooper.looper,
- Handler(mTestableLooper.looper),
- FalsingManagerFake(),
- mMetricsLogger,
- mStatusBarStateController,
- mActivityStarter,
- mQsLogger,
- mLocationController,
- mColorDisplayManager,
- mNightDisplayListenerBuilder
- )
+ mTile =
+ NightDisplayTile(
+ mHost,
+ mTestableLooper.looper,
+ Handler(mTestableLooper.looper),
+ FalsingManagerFake(),
+ mMetricsLogger,
+ mStatusBarStateController,
+ mActivityStarter,
+ mQsLogger,
+ mLocationController,
+ mColorDisplayManager,
+ mNightDisplayListenerBuilder
+ )
+ }
+
+ @After
+ fun tearDown() {
+ mTile.destroy()
+ mTestableLooper.processAllMessages()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
index 803187545a18..652c138f6478 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
@@ -32,11 +32,12 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -53,7 +54,7 @@ public class OneHandedModeTileTest extends SysuiTestCase {
@Mock
private ActivityStarter mActivityStarter;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -91,6 +92,12 @@ public class OneHandedModeTileTest extends SysuiTestCase {
mTile.initialize();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testIsAvailable_unsupportOneHandedProperty_shouldReturnsFalse() {
when(mTile.isSupportOneHandedMode()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
index a1be2f3ac8de..3125d455acfb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
@@ -39,10 +39,11 @@ import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qrcodescanner.controller.QRCodeScannerController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -54,7 +55,7 @@ import org.mockito.MockitoAnnotations;
@SmallTest
public class QRCodeScannerTileTest extends SysuiTestCase {
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -91,6 +92,12 @@ public class QRCodeScannerTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNewTile() {
assertFalse(mTile.newTileState().handlesLongClick);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index 4f6475f0148b..596df7856ee1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -66,13 +66,14 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -99,7 +100,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
.setComponent(new ComponentName(mContext.getPackageName(), "WalletActivity"));
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -161,6 +162,12 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNewTile() {
assertFalse(mTile.newTileState().handlesLongClick);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
index 8601d6c0a357..7913628c5693 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
@@ -38,12 +38,13 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.ReduceBrightColorsController;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -55,7 +56,7 @@ import org.mockito.MockitoAnnotations;
@SmallTest
public class ReduceBrightColorsTileTest extends SysuiTestCase {
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -97,6 +98,12 @@ public class ReduceBrightColorsTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNotActive() {
when(mReduceBrightColorsController.isReduceBrightColorsActivated()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
index e9dfd3ed182b..5b94cfedaedf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
@@ -38,7 +38,7 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -48,6 +48,7 @@ import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.wrapper.RotationPolicyWrapper;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -71,7 +72,7 @@ public class RotationLockTileTest extends SysuiTestCase {
@Mock
private ActivityStarter mActivityStarter;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -139,6 +140,12 @@ public class RotationLockTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mLockTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testSecondaryString_cameraRotateOn_returnsFaceBased() {
assertEquals(mContext.getString(R.string.rotation_lock_camera_rotation_on),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index 30debdf4b744..5aef75832fac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -43,13 +43,14 @@ import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,7 +66,7 @@ public class ScreenRecordTileTest extends SysuiTestCase {
@Mock
private RecordingController mController;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private KeyguardDismissUtil mKeyguardDismissUtil;
@Mock
@@ -114,6 +115,12 @@ public class ScreenRecordTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
// Test that the tile is inactive and labeled correctly when the controller is neither starting
// or recording, and that clicking on the tile in this state brings up the record prompt
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
index 0c070da1fcb9..b55657163382 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
@@ -32,13 +32,14 @@ import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.LocationController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -55,7 +56,7 @@ class UiModeNightTileTest : SysuiTestCase() {
@Mock private lateinit var uiModeManager: UiModeManager
@Mock private lateinit var resources: Resources
@Mock private lateinit var qsLogger: QSLogger
- @Mock private lateinit var qsHost: QSTileHost
+ @Mock private lateinit var qsHost: QSHost
@Mock private lateinit var metricsLogger: MetricsLogger
@Mock private lateinit var statusBarStateController: StatusBarStateController
@Mock private lateinit var activityStarter: ActivityStarter
@@ -98,6 +99,12 @@ class UiModeNightTileTest : SysuiTestCase() {
)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenNightModeOn_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
deleted file mode 100644
index e684007cb7c1..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
+++ /dev/null
@@ -1,319 +0,0 @@
-package com.android.systemui.shade
-
-import android.animation.Animator
-import android.app.StatusBarManager
-import android.content.Context
-import android.testing.AndroidTestingRunner
-import android.view.View
-import android.view.ViewPropertyAnimator
-import android.widget.TextView
-import androidx.test.filters.SmallTest
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.Interpolators
-import com.android.systemui.animation.ShadeInterpolation
-import com.android.systemui.battery.BatteryMeterView
-import com.android.systemui.battery.BatteryMeterViewController
-import com.android.systemui.demomode.DemoMode
-import com.android.systemui.demomode.DemoModeController
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.qs.HeaderPrivacyIconsController
-import com.android.systemui.qs.carrier.QSCarrierGroup
-import com.android.systemui.qs.carrier.QSCarrierGroupController
-import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
-import com.android.systemui.statusbar.phone.StatusBarIconController
-import com.android.systemui.statusbar.phone.StatusIconContainer
-import com.android.systemui.statusbar.policy.Clock
-import com.android.systemui.statusbar.policy.FakeConfigurationController
-import com.android.systemui.statusbar.policy.VariableDateViewController
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
-import com.android.systemui.util.mockito.capture
-import com.android.systemui.util.mockito.mock
-import com.google.common.truth.Truth.assertThat
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Answers
-import org.mockito.ArgumentMatchers.anyFloat
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.junit.MockitoJUnit
-import org.mockito.Mockito.`when` as whenever
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
-
- @Mock private lateinit var view: View
- @Mock private lateinit var statusIcons: StatusIconContainer
- @Mock private lateinit var statusBarIconController: StatusBarIconController
- @Mock private lateinit var iconManagerFactory: StatusBarIconController.TintedIconManager.Factory
- @Mock private lateinit var iconManager: StatusBarIconController.TintedIconManager
- @Mock private lateinit var qsCarrierGroupController: QSCarrierGroupController
- @Mock private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
- @Mock private lateinit var featureFlags: FeatureFlags
- @Mock private lateinit var clock: Clock
- @Mock private lateinit var date: TextView
- @Mock private lateinit var carrierGroup: QSCarrierGroup
- @Mock private lateinit var batteryMeterView: BatteryMeterView
- @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
- @Mock private lateinit var privacyIconsController: HeaderPrivacyIconsController
- @Mock private lateinit var insetsProvider: StatusBarContentInsetsProvider
- @Mock private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory
- @Mock private lateinit var variableDateViewController: VariableDateViewController
- @Mock private lateinit var dumpManager: DumpManager
- @Mock private lateinit var combinedShadeHeadersConstraintManager:
- CombinedShadeHeadersConstraintManager
-
- @Mock private lateinit var mockedContext: Context
- @Mock private lateinit var demoModeController: DemoModeController
- @Mock private lateinit var qsBatteryModeController: QsBatteryModeController
-
- @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
- var viewVisibility = View.GONE
- var viewAlpha = 1f
-
- private lateinit var mLargeScreenShadeHeaderController: LargeScreenShadeHeaderController
- private lateinit var carrierIconSlots: List<String>
- private val configurationController = FakeConfigurationController()
-
- @Before
- fun setup() {
- whenever<Clock>(view.findViewById(R.id.clock)).thenReturn(clock)
- whenever(clock.context).thenReturn(mockedContext)
- whenever<TextView>(view.findViewById(R.id.date)).thenReturn(date)
- whenever(date.context).thenReturn(mockedContext)
- whenever<QSCarrierGroup>(view.findViewById(R.id.carrier_group)).thenReturn(carrierGroup)
- whenever<BatteryMeterView>(view.findViewById(R.id.batteryRemainingIcon))
- .thenReturn(batteryMeterView)
- whenever<StatusIconContainer>(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons)
- whenever(view.context).thenReturn(context)
- whenever(view.resources).thenReturn(context.resources)
- whenever(statusIcons.context).thenReturn(context)
- whenever(qsCarrierGroupControllerBuilder.setQSCarrierGroup(any()))
- .thenReturn(qsCarrierGroupControllerBuilder)
- whenever(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
- whenever(view.setVisibility(anyInt())).then {
- viewVisibility = it.arguments[0] as Int
- null
- }
- whenever(view.visibility).thenAnswer { _ -> viewVisibility }
-
- whenever(view.setAlpha(anyFloat())).then {
- viewAlpha = it.arguments[0] as Float
- null
- }
- whenever(view.alpha).thenAnswer { _ -> viewAlpha }
-
- whenever(variableDateViewControllerFactory.create(any()))
- .thenReturn(variableDateViewController)
- whenever(iconManagerFactory.create(any(), any())).thenReturn(iconManager)
- whenever(featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)).thenReturn(false)
- mLargeScreenShadeHeaderController = LargeScreenShadeHeaderController(
- view,
- statusBarIconController,
- iconManagerFactory,
- privacyIconsController,
- insetsProvider,
- configurationController,
- variableDateViewControllerFactory,
- batteryMeterViewController,
- dumpManager,
- featureFlags,
- qsCarrierGroupControllerBuilder,
- combinedShadeHeadersConstraintManager,
- demoModeController,
- qsBatteryModeController,
- )
- whenever(view.isAttachedToWindow).thenReturn(true)
- mLargeScreenShadeHeaderController.init()
- carrierIconSlots = listOf(
- context.getString(com.android.internal.R.string.status_bar_mobile))
- }
-
- @After
- fun verifyEveryTest() {
- verifyZeroInteractions(combinedShadeHeadersConstraintManager)
- }
-
- @Test
- fun setVisible_onlyWhenActive() {
- makeShadeVisible()
- assertThat(viewVisibility).isEqualTo(View.VISIBLE)
-
- mLargeScreenShadeHeaderController.largeScreenActive = false
- assertThat(viewVisibility).isEqualTo(View.GONE)
- }
-
- @Test
- fun updateListeners_registersWhenVisible() {
- makeShadeVisible()
- verify(qsCarrierGroupController).setListening(true)
- }
-
- @Test
- fun statusIconsAddedWhenAttached() {
- verify(statusBarIconController).addIconGroup(any())
- }
-
- @Test
- fun statusIconsRemovedWhenDettached() {
- mLargeScreenShadeHeaderController.simulateViewDetached()
- verify(statusBarIconController).removeIconGroup(any())
- }
-
- @Test
- fun shadeExpandedFraction_updatesAlpha() {
- makeShadeVisible()
- mLargeScreenShadeHeaderController.shadeExpandedFraction = 0.5f
- verify(view).setAlpha(ShadeInterpolation.getContentAlpha(0.5f))
- }
-
- @Test
- fun singleCarrier_enablesCarrierIconsInStatusIcons() {
- whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(true)
-
- makeShadeVisible()
-
- verify(statusIcons).removeIgnoredSlots(carrierIconSlots)
- }
-
- @Test
- fun dualCarrier_disablesCarrierIconsInStatusIcons() {
- whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(false)
-
- makeShadeVisible()
-
- verify(statusIcons).addIgnoredSlots(carrierIconSlots)
- }
-
- @Test
- fun disableQS_notDisabled_visible() {
- makeShadeVisible()
- mLargeScreenShadeHeaderController.disable(0, 0, false)
-
- assertThat(viewVisibility).isEqualTo(View.VISIBLE)
- }
-
- @Test
- fun disableQS_disabled_gone() {
- makeShadeVisible()
- mLargeScreenShadeHeaderController.disable(0, StatusBarManager.DISABLE2_QUICK_SETTINGS,
- false)
-
- assertThat(viewVisibility).isEqualTo(View.GONE)
- }
-
- private fun makeShadeVisible() {
- mLargeScreenShadeHeaderController.largeScreenActive = true
- mLargeScreenShadeHeaderController.qsVisible = true
- }
-
- @Test
- fun updateConfig_changesFontStyle() {
- configurationController.notifyDensityOrFontScaleChanged()
-
- verify(clock).setTextAppearance(R.style.TextAppearance_QS_Status)
- verify(date).setTextAppearance(R.style.TextAppearance_QS_Status)
- verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status_Carriers)
- }
-
- @Test
- fun alarmIconIgnored() {
- verify(statusIcons).addIgnoredSlot(
- context.getString(com.android.internal.R.string.status_bar_alarm_clock)
- )
- }
-
- @Test
- fun animateOutOnStartCustomizing() {
- val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- val duration = 1000L
- whenever(view.animate()).thenReturn(animator)
-
- mLargeScreenShadeHeaderController.startCustomizingAnimation(show = true, duration)
-
- verify(animator).setDuration(duration)
- verify(animator).alpha(0f)
- verify(animator).setInterpolator(Interpolators.ALPHA_OUT)
- verify(animator).start()
- }
-
- @Test
- fun animateInOnEndCustomizing() {
- val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- val duration = 1000L
- whenever(view.animate()).thenReturn(animator)
-
- mLargeScreenShadeHeaderController.startCustomizingAnimation(show = false, duration)
-
- verify(animator).setDuration(duration)
- verify(animator).alpha(1f)
- verify(animator).setInterpolator(Interpolators.ALPHA_IN)
- verify(animator).start()
- }
-
- @Test
- fun customizerAnimatorChangesViewVisibility() {
- makeShadeVisible()
-
- val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- val duration = 1000L
- whenever(view.animate()).thenReturn(animator)
- val listenerCaptor = argumentCaptor<Animator.AnimatorListener>()
-
- mLargeScreenShadeHeaderController.startCustomizingAnimation(show = true, duration)
- verify(animator).setListener(capture(listenerCaptor))
- // Start and end the animation
- listenerCaptor.value.onAnimationStart(mock())
- listenerCaptor.value.onAnimationEnd(mock())
- assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
-
- reset(animator)
- mLargeScreenShadeHeaderController.startCustomizingAnimation(show = false, duration)
- verify(animator).setListener(capture(listenerCaptor))
- // Start and end the animation
- listenerCaptor.value.onAnimationStart(mock())
- listenerCaptor.value.onAnimationEnd(mock())
- assertThat(viewVisibility).isEqualTo(View.VISIBLE)
- }
-
- @Test
- fun animatorListenerClearedAtEnd() {
- val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- whenever(view.animate()).thenReturn(animator)
-
- mLargeScreenShadeHeaderController.startCustomizingAnimation(show = true, 0L)
- val listenerCaptor = argumentCaptor<Animator.AnimatorListener>()
- verify(animator).setListener(capture(listenerCaptor))
-
- listenerCaptor.value.onAnimationEnd(mock())
- verify(animator).setListener(null)
- }
-
- @Test
- fun demoMode_attachDemoMode() {
- val cb = argumentCaptor<DemoMode>()
- verify(demoModeController).addCallback(capture(cb))
- cb.value.onDemoModeStarted()
- verify(clock).onDemoModeStarted()
- }
-
- @Test
- fun demoMode_detachDemoMode() {
- mLargeScreenShadeHeaderController.simulateViewDetached()
- val cb = argumentCaptor<DemoMode>()
- verify(demoModeController).removeCallback(capture(cb))
- cb.value.onDemoModeFinished()
- verify(clock).onDemoModeFinished()
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
new file mode 100644
index 000000000000..99cf8d0ebe93
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -0,0 +1,752 @@
+/*
+ * 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 static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+
+import static com.android.keyguard.KeyguardClockSwitch.LARGE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
+import android.annotation.IdRes;
+import android.content.ContentResolver;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.UserManager;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.ViewPropertyAnimator;
+import android.view.ViewStub;
+import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.constraintlayout.widget.ConstraintSet;
+
+import com.android.internal.jank.InteractionJankMonitor;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.testing.UiEventLoggerFake;
+import com.android.internal.util.LatencyTracker;
+import com.android.keyguard.KeyguardClockSwitch;
+import com.android.keyguard.KeyguardClockSwitchController;
+import com.android.keyguard.KeyguardStatusView;
+import com.android.keyguard.KeyguardStatusViewController;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.LockIconViewController;
+import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
+import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
+import com.android.keyguard.dagger.KeyguardStatusViewComponent;
+import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.classifier.FalsingCollectorFake;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.common.ui.view.LongPressHandlingView;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
+import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel;
+import com.android.systemui.media.controls.pipeline.MediaDataManager;
+import com.android.systemui.media.controls.ui.KeyguardMediaController;
+import com.android.systemui.media.controls.ui.MediaHierarchyManager;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.qs.QSFragment;
+import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.shade.transition.ShadeTransitionController;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.NotificationShelfController;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.QsFrameTranslateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.ConversationNotificationManager;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinatorLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.stack.AmbientState;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
+import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
+import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
+import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
+import com.android.systemui.statusbar.phone.TapAgainViewController;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
+import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
+import com.android.systemui.unfold.SysUIUnfoldComponent;
+import com.android.systemui.util.time.FakeSystemClock;
+import com.android.systemui.util.time.SystemClock;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+
+import java.util.List;
+import java.util.Optional;
+
+import dagger.Lazy;
+import kotlinx.coroutines.CoroutineDispatcher;
+
+public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
+
+ protected static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
+ protected static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
+ protected static final int PANEL_WIDTH = 500; // Random value just for the test.
+
+ @Mock protected CentralSurfaces mCentralSurfaces;
+ @Mock protected NotificationStackScrollLayout mNotificationStackScrollLayout;
+ @Mock protected KeyguardBottomAreaView mKeyguardBottomArea;
+ @Mock protected KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
+ @Mock protected KeyguardBottomAreaView mQsFrame;
+ @Mock protected HeadsUpManagerPhone mHeadsUpManager;
+ @Mock protected NotificationShelfController mNotificationShelfController;
+ @Mock protected NotificationGutsManager mGutsManager;
+ @Mock protected KeyguardStatusBarView mKeyguardStatusBar;
+ @Mock protected KeyguardUserSwitcherView mUserSwitcherView;
+ @Mock protected ViewStub mUserSwitcherStubView;
+ @Mock protected HeadsUpTouchHelper.Callback mHeadsUpCallback;
+ @Mock protected KeyguardUpdateMonitor mUpdateMonitor;
+ @Mock protected KeyguardBypassController mKeyguardBypassController;
+ @Mock protected DozeParameters mDozeParameters;
+ @Mock protected ScreenOffAnimationController mScreenOffAnimationController;
+ @Mock protected NotificationPanelView mView;
+ @Mock protected LayoutInflater mLayoutInflater;
+ @Mock protected FeatureFlags mFeatureFlags;
+ @Mock protected DynamicPrivacyController mDynamicPrivacyController;
+ @Mock protected StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
+ @Mock protected KeyguardStateController mKeyguardStateController;
+ @Mock protected DozeLog mDozeLog;
+ @Mock protected ShadeLogger mShadeLog;
+ @Mock protected ShadeHeightLogger mShadeHeightLogger;
+ @Mock protected CommandQueue mCommandQueue;
+ @Mock protected VibratorHelper mVibratorHelper;
+ @Mock protected LatencyTracker mLatencyTracker;
+ @Mock protected PowerManager mPowerManager;
+ @Mock protected AccessibilityManager mAccessibilityManager;
+ @Mock protected MetricsLogger mMetricsLogger;
+ @Mock protected Resources mResources;
+ @Mock protected Configuration mConfiguration;
+ @Mock protected KeyguardClockSwitch mKeyguardClockSwitch;
+ @Mock protected MediaHierarchyManager mMediaHierarchyManager;
+ @Mock protected ConversationNotificationManager mConversationNotificationManager;
+ @Mock protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ @Mock protected KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
+ @Mock protected KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
+ @Mock protected KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
+ @Mock protected KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
+ @Mock protected KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
+ @Mock protected KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
+ @Mock protected KeyguardUserSwitcherController mKeyguardUserSwitcherController;
+ @Mock protected KeyguardStatusViewComponent mKeyguardStatusViewComponent;
+ @Mock protected KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
+ @Mock protected KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
+ @Mock protected KeyguardClockSwitchController mKeyguardClockSwitchController;
+ @Mock protected KeyguardStatusViewController mKeyguardStatusViewController;
+ @Mock protected KeyguardStatusBarViewController mKeyguardStatusBarViewController;
+ @Mock protected NotificationStackScrollLayoutController
+ mNotificationStackScrollLayoutController;
+ @Mock protected NotificationShadeDepthController mNotificationShadeDepthController;
+ @Mock protected LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+ @Mock protected AuthController mAuthController;
+ @Mock protected ScrimController mScrimController;
+ @Mock protected MediaDataManager mMediaDataManager;
+ @Mock protected AmbientState mAmbientState;
+ @Mock protected UserManager mUserManager;
+ @Mock protected UiEventLogger mUiEventLogger;
+ @Mock protected LockIconViewController mLockIconViewController;
+ @Mock protected KeyguardMediaController mKeyguardMediaController;
+ @Mock protected NavigationModeController mNavigationModeController;
+ @Mock protected NavigationBarController mNavigationBarController;
+ @Mock protected QuickSettingsController mQsController;
+ @Mock protected ShadeHeaderController mShadeHeaderController;
+ @Mock protected ContentResolver mContentResolver;
+ @Mock protected TapAgainViewController mTapAgainViewController;
+ @Mock protected KeyguardIndicationController mKeyguardIndicationController;
+ @Mock protected FragmentService mFragmentService;
+ @Mock protected FragmentHostManager mFragmentHostManager;
+ @Mock protected NotificationRemoteInputManager mNotificationRemoteInputManager;
+ @Mock protected RecordingController mRecordingController;
+ @Mock protected LockscreenGestureLogger mLockscreenGestureLogger;
+ @Mock protected DumpManager mDumpManager;
+ @Mock protected InteractionJankMonitor mInteractionJankMonitor;
+ @Mock protected NotificationsQSContainerController mNotificationsQSContainerController;
+ @Mock protected QsFrameTranslateController mQsFrameTranslateController;
+ @Mock protected StatusBarWindowStateController mStatusBarWindowStateController;
+ @Mock protected KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+ @Mock protected NotificationShadeWindowController mNotificationShadeWindowController;
+ @Mock protected SysUiState mSysUiState;
+ @Mock protected NotificationListContainer mNotificationListContainer;
+ @Mock protected NotificationStackSizeCalculator mNotificationStackSizeCalculator;
+ @Mock protected UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+ @Mock protected ShadeTransitionController mShadeTransitionController;
+ @Mock protected QS mQs;
+ @Mock protected QSFragment mQSFragment;
+ @Mock protected ViewGroup mQsHeader;
+ @Mock protected ViewParent mViewParent;
+ @Mock protected ViewTreeObserver mViewTreeObserver;
+ @Mock protected KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
+ @Mock protected DreamingToLockscreenTransitionViewModel
+ mDreamingToLockscreenTransitionViewModel;
+ @Mock protected OccludedToLockscreenTransitionViewModel
+ mOccludedToLockscreenTransitionViewModel;
+ @Mock protected LockscreenToDreamingTransitionViewModel
+ mLockscreenToDreamingTransitionViewModel;
+ @Mock protected LockscreenToOccludedTransitionViewModel
+ mLockscreenToOccludedTransitionViewModel;
+ @Mock protected GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
+
+ @Mock protected KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+ @Mock protected KeyguardLongPressViewModel mKeyuardLongPressViewModel;
+ @Mock protected AlternateBouncerInteractor mAlternateBouncerInteractor;
+ @Mock protected MotionEvent mDownMotionEvent;
+ @Mock protected CoroutineDispatcher mMainDispatcher;
+ @Captor
+ protected ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
+ mEmptySpaceClickListenerCaptor;
+
+ protected KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
+ protected KeyguardInteractor mKeyguardInteractor;
+ protected NotificationPanelViewController.TouchHandler mTouchHandler;
+ protected ConfigurationController mConfigurationController;
+ protected SysuiStatusBarStateController mStatusBarStateController;
+ protected NotificationPanelViewController mNotificationPanelViewController;
+ protected View.AccessibilityDelegate mAccessibilityDelegate;
+ protected NotificationsQuickSettingsContainer mNotificationContainerParent;
+ protected List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
+ protected Handler mMainHandler;
+ protected View.OnLayoutChangeListener mLayoutChangeListener;
+
+ protected final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
+ protected final Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
+ protected final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+ protected final ShadeExpansionStateManager mShadeExpansionStateManager =
+ new ShadeExpansionStateManager();
+
+ protected QuickSettingsController mQuickSettingsController;
+ @Mock protected Lazy<NotificationPanelViewController> mNotificationPanelViewControllerLazy;
+
+ protected FragmentHostManager.FragmentListener mFragmentListener;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mMainDispatcher = getMainDispatcher();
+ mKeyguardBottomAreaInteractor = new KeyguardBottomAreaInteractor(
+ new FakeKeyguardRepository());
+ mKeyguardInteractor = new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue,
+ mFeatureFlags, new FakeKeyguardBouncerRepository());
+ SystemClock systemClock = new FakeSystemClock();
+ mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
+ mInteractionJankMonitor, mShadeExpansionStateManager);
+
+ KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
+ keyguardStatusView.setId(R.id.keyguard_status_view);
+
+ when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
+ when(mHeadsUpCallback.getContext()).thenReturn(mContext);
+ when(mView.getResources()).thenReturn(mResources);
+ when(mView.getWidth()).thenReturn(PANEL_WIDTH);
+ when(mResources.getConfiguration()).thenReturn(mConfiguration);
+ mConfiguration.orientation = ORIENTATION_PORTRAIT;
+ when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
+ mDisplayMetrics.density = 100;
+ when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
+ when(mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade))
+ .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
+ when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
+ .thenReturn(10);
+ when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
+ .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
+ when(mView.getContext()).thenReturn(getContext());
+ when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
+ when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
+ when(mView.findViewById(R.id.keyguard_user_switcher_stub)).thenReturn(
+ mUserSwitcherStubView);
+ when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
+ when(mView.findViewById(R.id.notification_stack_scroller))
+ .thenReturn(mNotificationStackScrollLayout);
+ when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
+ when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
+ .thenReturn(mHeadsUpCallback);
+ when(mKeyguardBottomAreaViewController.getView()).thenReturn(mKeyguardBottomArea);
+ when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
+ when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class));
+ when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
+ when(mView.findViewById(R.id.keyguard_status_view))
+ .thenReturn(mock(KeyguardStatusView.class));
+ mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
+ mNotificationContainerParent.addView(keyguardStatusView);
+ mNotificationContainerParent.onFinishInflate();
+ when(mView.findViewById(R.id.notification_container_parent))
+ .thenReturn(mNotificationContainerParent);
+ when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
+ FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
+ mDisplayMetrics);
+ when(mKeyguardQsUserSwitchComponentFactory.build(any()))
+ .thenReturn(mKeyguardQsUserSwitchComponent);
+ when(mKeyguardQsUserSwitchComponent.getKeyguardQsUserSwitchController())
+ .thenReturn(mKeyguardQsUserSwitchController);
+ when(mKeyguardUserSwitcherComponentFactory.build(any()))
+ .thenReturn(mKeyguardUserSwitcherComponent);
+ when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController())
+ .thenReturn(mKeyguardUserSwitcherController);
+ when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
+ when(mQs.getView()).thenReturn(mView);
+ when(mQSFragment.getView()).thenReturn(mView);
+ doAnswer(invocation -> {
+ mFragmentListener = invocation.getArgument(1);
+ return null;
+ }).when(mFragmentHostManager).addTagListener(eq(QS.TAG), any());
+ doAnswer((Answer<Void>) invocation -> {
+ mTouchHandler = invocation.getArgument(0);
+ return null;
+ }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class));
+
+ // Dreaming->Lockscreen
+ when(mKeyguardTransitionInteractor.getDreamingToLockscreenTransition())
+ .thenReturn(emptyFlow());
+ when(mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha())
+ .thenReturn(emptyFlow());
+ when(mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
+ .thenReturn(emptyFlow());
+
+ // Occluded->Lockscreen
+ when(mKeyguardTransitionInteractor.getOccludedToLockscreenTransition())
+ .thenReturn(emptyFlow());
+ when(mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha())
+ .thenReturn(emptyFlow());
+ when(mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
+ .thenReturn(emptyFlow());
+
+ // Lockscreen->Dreaming
+ when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition())
+ .thenReturn(emptyFlow());
+ when(mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha())
+ .thenReturn(emptyFlow());
+ when(mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
+ .thenReturn(emptyFlow());
+
+ // Gone->Dreaming
+ when(mKeyguardTransitionInteractor.getGoneToDreamingTransition())
+ .thenReturn(emptyFlow());
+ when(mGoneToDreamingTransitionViewModel.getLockscreenAlpha())
+ .thenReturn(emptyFlow());
+ when(mGoneToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
+ .thenReturn(emptyFlow());
+
+ // Lockscreen->Occluded
+ when(mKeyguardTransitionInteractor.getLockscreenToOccludedTransition())
+ .thenReturn(emptyFlow());
+ when(mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha())
+ .thenReturn(emptyFlow());
+ when(mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(anyInt()))
+ .thenReturn(emptyFlow());
+
+ NotificationWakeUpCoordinator coordinator =
+ new NotificationWakeUpCoordinator(
+ mDumpManager,
+ mock(HeadsUpManagerPhone.class),
+ new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
+ mInteractionJankMonitor, mShadeExpansionStateManager),
+ mKeyguardBypassController,
+ mDozeParameters,
+ mScreenOffAnimationController,
+ mock(NotificationWakeUpCoordinatorLogger.class));
+ mConfigurationController = new ConfigurationControllerImpl(mContext);
+ PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
+ mContext,
+ coordinator,
+ mKeyguardBypassController, mHeadsUpManager,
+ mock(NotificationRoundnessManager.class),
+ mConfigurationController,
+ mStatusBarStateController,
+ mFalsingManager,
+ mShadeExpansionStateManager,
+ mLockscreenShadeTransitionController,
+ new FalsingCollectorFake(),
+ mDumpManager);
+ when(mKeyguardStatusViewComponentFactory.build(any()))
+ .thenReturn(mKeyguardStatusViewComponent);
+ when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
+ .thenReturn(mKeyguardClockSwitchController);
+ when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
+ .thenReturn(mKeyguardStatusViewController);
+ when(mKeyguardStatusBarViewComponentFactory.build(any(), any()))
+ .thenReturn(mKeyguardStatusBarViewComponent);
+ when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
+ .thenReturn(mKeyguardStatusBarViewController);
+ when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
+ .thenReturn(keyguardStatusView);
+ when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
+ .thenReturn(mUserSwitcherView);
+ when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean()))
+ .thenReturn(mKeyguardBottomArea);
+ when(mNotificationRemoteInputManager.isRemoteInputActive())
+ .thenReturn(false);
+ when(mInteractionJankMonitor.begin(any(), anyInt()))
+ .thenReturn(true);
+ when(mInteractionJankMonitor.end(anyInt()))
+ .thenReturn(true);
+ doAnswer(invocation -> {
+ ((Runnable) invocation.getArgument(0)).run();
+ return null;
+ }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
+ doAnswer(invocation -> {
+ mLayoutChangeListener = invocation.getArgument(0);
+ return null;
+ }).when(mView).addOnLayoutChangeListener(any());
+
+ when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
+ when(mView.getParent()).thenReturn(mViewParent);
+ when(mQs.getHeader()).thenReturn(mQsHeader);
+ when(mDownMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_DOWN);
+ when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
+
+ mMainHandler = new Handler(Looper.getMainLooper());
+
+ when(mView.requireViewById(R.id.keyguard_long_press))
+ .thenReturn(mock(LongPressHandlingView.class));
+
+ mNotificationPanelViewController = new NotificationPanelViewController(
+ mView,
+ mMainHandler,
+ mLayoutInflater,
+ mFeatureFlags,
+ coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
+ mFalsingManager, new FalsingCollectorFake(),
+ mKeyguardStateController,
+ mStatusBarStateController,
+ mStatusBarWindowStateController,
+ mNotificationShadeWindowController,
+ mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper,
+ mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
+ mMetricsLogger,
+ mShadeLog,
+ mShadeHeightLogger,
+ mConfigurationController,
+ () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
+ mConversationNotificationManager, mMediaHierarchyManager,
+ mStatusBarKeyguardViewManager,
+ mGutsManager,
+ mNotificationsQSContainerController,
+ mNotificationStackScrollLayoutController,
+ mKeyguardStatusViewComponentFactory,
+ mKeyguardQsUserSwitchComponentFactory,
+ mKeyguardUserSwitcherComponentFactory,
+ mKeyguardStatusBarViewComponentFactory,
+ mLockscreenShadeTransitionController,
+ mAuthController,
+ mScrimController,
+ mUserManager,
+ mMediaDataManager,
+ mNotificationShadeDepthController,
+ mAmbientState,
+ mLockIconViewController,
+ mKeyguardMediaController,
+ mTapAgainViewController,
+ mNavigationModeController,
+ mNavigationBarController,
+ mQsController,
+ mFragmentService,
+ mContentResolver,
+ mShadeHeaderController,
+ mScreenOffAnimationController,
+ mLockscreenGestureLogger,
+ mShadeExpansionStateManager,
+ mSysUIUnfoldComponent,
+ mSysUiState,
+ () -> mKeyguardBottomAreaViewController,
+ mKeyguardUnlockAnimationController,
+ mKeyguardIndicationController,
+ mNotificationListContainer,
+ mNotificationStackSizeCalculator,
+ mUnlockedScreenOffAnimationController,
+ mShadeTransitionController,
+ mInteractionJankMonitor,
+ systemClock,
+ mKeyguardBottomAreaViewModel,
+ mKeyguardBottomAreaInteractor,
+ mAlternateBouncerInteractor,
+ mDreamingToLockscreenTransitionViewModel,
+ mOccludedToLockscreenTransitionViewModel,
+ mLockscreenToDreamingTransitionViewModel,
+ mGoneToDreamingTransitionViewModel,
+ mLockscreenToOccludedTransitionViewModel,
+ mMainDispatcher,
+ mKeyguardTransitionInteractor,
+ mDumpManager,
+ mKeyuardLongPressViewModel,
+ mKeyguardInteractor);
+ mNotificationPanelViewController.initDependencies(
+ mCentralSurfaces,
+ null,
+ () -> {},
+ mNotificationShelfController);
+ mNotificationPanelViewController.setTrackingStartedListener(() -> {});
+ mNotificationPanelViewController.setOpenCloseListener(
+ new NotificationPanelViewController.OpenCloseListener() {
+ @Override
+ public void onClosingFinished() {}
+
+ @Override
+ public void onOpenStarted() {}
+ });
+ mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
+ ArgumentCaptor<View.OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
+ ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
+ verify(mView, atLeast(1)).addOnAttachStateChangeListener(
+ onAttachStateChangeListenerArgumentCaptor.capture());
+ mOnAttachStateChangeListeners = onAttachStateChangeListenerArgumentCaptor.getAllValues();
+
+ ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
+ ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
+ verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
+ mAccessibilityDelegate = accessibilityDelegateArgumentCaptor.getValue();
+ mNotificationPanelViewController.getStatusBarStateController()
+ .addCallback(mNotificationPanelViewController.getStatusBarStateListener());
+ mNotificationPanelViewController
+ .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
+ verify(mNotificationStackScrollLayoutController)
+ .setOnEmptySpaceClickListener(mEmptySpaceClickListenerCaptor.capture());
+ verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
+ reset(mKeyguardStatusViewController);
+
+ when(mNotificationPanelViewControllerLazy.get())
+ .thenReturn(mNotificationPanelViewController);
+ mQuickSettingsController = new QuickSettingsController(
+ mNotificationPanelViewControllerLazy,
+ mView,
+ mQsFrameTranslateController,
+ mShadeTransitionController,
+ expansionHandler,
+ mNotificationRemoteInputManager,
+ mShadeExpansionStateManager,
+ mStatusBarKeyguardViewManager,
+ mNotificationStackScrollLayoutController,
+ mLockscreenShadeTransitionController,
+ mNotificationShadeDepthController,
+ mShadeHeaderController,
+ mStatusBarTouchableRegionManager,
+ mKeyguardStateController,
+ mKeyguardBypassController,
+ mUpdateMonitor,
+ mScrimController,
+ mMediaDataManager,
+ mMediaHierarchyManager,
+ mAmbientState,
+ mRecordingController,
+ mFalsingManager,
+ new FalsingCollectorFake(),
+ mAccessibilityManager,
+ mLockscreenGestureLogger,
+ mMetricsLogger,
+ mFeatureFlags,
+ mInteractionJankMonitor,
+ mShadeLog
+ );
+ }
+
+ @After
+ public void tearDown() {
+ mNotificationPanelViewController.mBottomAreaShadeAlphaAnimator.cancel();
+ mNotificationPanelViewController.cancelHeightAnimator();
+ mMainHandler.removeCallbacksAndMessages(null);
+ }
+
+ protected void setBottomPadding(int stackBottom, int lockIconPadding, int indicationPadding,
+ int ambientPadding) {
+
+ when(mNotificationStackScrollLayoutController.getTop()).thenReturn(0);
+ when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(stackBottom);
+ when(mNotificationStackScrollLayoutController.getBottom()).thenReturn(stackBottom);
+ when(mLockIconViewController.getTop()).thenReturn((float) (stackBottom - lockIconPadding));
+
+ when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
+ .thenReturn(indicationPadding);
+ mNotificationPanelViewController.loadDimens();
+
+ mNotificationPanelViewController.setAmbientIndicationTop(
+ /* ambientIndicationTop= */ stackBottom - ambientPadding,
+ /* ambientTextVisible= */ true);
+ }
+
+ protected void triggerPositionClockAndNotifications() {
+ mNotificationPanelViewController.onQsSetExpansionHeightCalled(false);
+ }
+
+ protected FalsingManager.FalsingTapListener getFalsingTapListener() {
+ for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
+ listener.onViewAttachedToWindow(mView);
+ }
+ assertThat(mFalsingManager.getTapListeners().size()).isEqualTo(1);
+ return mFalsingManager.getTapListeners().get(0);
+ }
+
+ protected void givenViewAttached() {
+ for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
+ listener.onViewAttachedToWindow(mView);
+ }
+ }
+
+ protected ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
+ ConstraintSet constraintSet = new ConstraintSet();
+ constraintSet.clone(mNotificationContainerParent);
+ return constraintSet.getConstraint(id).layout;
+ }
+
+ protected void enableSplitShade(boolean enabled) {
+ when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled);
+ mNotificationPanelViewController.updateResources();
+ }
+
+ protected void updateMultiUserSetting(boolean enabled) {
+ when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+ when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
+ final ArgumentCaptor<ContentObserver> observerCaptor =
+ ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mContentResolver)
+ .registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
+ observerCaptor.getValue().onChange(/* selfChange */ false);
+ }
+
+ protected void updateSmallestScreenWidth(int smallestScreenWidthDp) {
+ Configuration configuration = new Configuration();
+ configuration.smallestScreenWidthDp = smallestScreenWidthDp;
+ mConfigurationController.onConfigurationChanged(configuration);
+ }
+
+ protected void onTouchEvent(MotionEvent ev) {
+ mTouchHandler.onTouch(mView, ev);
+ }
+
+ protected void setDozing(boolean dozing, boolean dozingAlwaysOn) {
+ when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn);
+ mNotificationPanelViewController.setDozing(
+ /* dozing= */ dozing,
+ /* animate= */ false
+ );
+ }
+
+ protected void assertKeyguardStatusViewCentered() {
+ mNotificationPanelViewController.updateResources();
+ assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isAnyOf(
+ ConstraintSet.PARENT_ID, ConstraintSet.UNSET);
+ }
+
+ protected void assertKeyguardStatusViewNotCentered() {
+ mNotificationPanelViewController.updateResources();
+ assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo(
+ R.id.qs_edge_guideline);
+ }
+
+ protected void setIsFullWidth(boolean fullWidth) {
+ float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f;
+ when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth);
+ triggerLayoutChange();
+ }
+
+ protected void triggerLayoutChange() {
+ mLayoutChangeListener.onLayoutChange(
+ mView,
+ /* left= */ 0,
+ /* top= */ 0,
+ /* right= */ 0,
+ /* bottom= */ 0,
+ /* oldLeft= */ 0,
+ /* oldTop= */ 0,
+ /* oldRight= */ 0,
+ /* oldBottom= */ 0
+ );
+ }
+
+ protected CoroutineDispatcher getMainDispatcher() {
+ return mMainDispatcher;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 996d9fb5bfb8..4517596e8b02 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -16,8 +16,6 @@
package com.android.systemui.shade;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
@@ -31,15 +29,11 @@ import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -48,575 +42,41 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.annotation.IdRes;
-import android.content.ContentResolver;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.PowerManager;
-import android.os.UserManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.util.DisplayMetrics;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.ViewPropertyAnimator;
-import android.view.ViewStub;
-import android.view.ViewTreeObserver;
-import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.test.filters.SmallTest;
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.testing.UiEventLoggerFake;
-import com.android.internal.util.CollectionUtils;
-import com.android.internal.util.LatencyTracker;
import com.android.keyguard.FaceAuthApiRequestReason;
-import com.android.keyguard.KeyguardClockSwitch;
-import com.android.keyguard.KeyguardClockSwitchController;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.keyguard.KeyguardStatusViewController;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.LockIconViewController;
-import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
-import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
-import com.android.keyguard.dagger.KeyguardStatusViewComponent;
-import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
import com.android.systemui.DejankUtils;
import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.classifier.FalsingCollectorFake;
-import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.common.ui.view.LongPressHandlingView;
-import com.android.systemui.doze.DozeLog;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.fragments.FragmentService;
-import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel;
-import com.android.systemui.media.controls.pipeline.MediaDataManager;
-import com.android.systemui.media.controls.ui.KeyguardMediaController;
-import com.android.systemui.media.controls.ui.MediaHierarchyManager;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationBarController;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSFragment;
-import com.android.systemui.screenrecord.RecordingController;
-import com.android.systemui.shade.transition.ShadeTransitionController;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.LockscreenShadeTransitionController;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationShadeDepthController;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.NotificationShelfController;
-import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.QsFrameTranslateController;
-import com.android.systemui.statusbar.StatusBarStateControllerImpl;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.ConversationNotificationManager;
-import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinatorLogger;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.AmbientState;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
-import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
-import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
-import com.android.systemui.statusbar.phone.TapAgainViewController;
-import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
-import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.unfold.SysUIUnfoldComponent;
-import com.android.systemui.util.time.FakeSystemClock;
-import com.android.systemui.util.time.SystemClock;
-import com.android.wm.shell.animation.FlingAnimationUtils;
-
-import org.junit.After;
+
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
import java.util.List;
-import java.util.Optional;
-
-import dagger.Lazy;
-import kotlinx.coroutines.CoroutineDispatcher;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class NotificationPanelViewControllerTest extends SysuiTestCase {
-
- private static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
- private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
- private static final int PANEL_WIDTH = 500; // Random value just for the test.
-
- @Mock private CentralSurfaces mCentralSurfaces;
- @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout;
- @Mock private KeyguardBottomAreaView mKeyguardBottomArea;
- @Mock private KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
- @Mock private KeyguardBottomAreaView mQsFrame;
- @Mock private HeadsUpManagerPhone mHeadsUpManager;
- @Mock private NotificationShelfController mNotificationShelfController;
- @Mock private NotificationGutsManager mGutsManager;
- @Mock private KeyguardStatusBarView mKeyguardStatusBar;
- @Mock private KeyguardUserSwitcherView mUserSwitcherView;
- @Mock private ViewStub mUserSwitcherStubView;
- @Mock private HeadsUpTouchHelper.Callback mHeadsUpCallback;
- @Mock private KeyguardUpdateMonitor mUpdateMonitor;
- @Mock private KeyguardBypassController mKeyguardBypassController;
- @Mock private DozeParameters mDozeParameters;
- @Mock private ScreenOffAnimationController mScreenOffAnimationController;
- @Mock private NotificationPanelView mView;
- @Mock private LayoutInflater mLayoutInflater;
- @Mock private FeatureFlags mFeatureFlags;
- @Mock private DynamicPrivacyController mDynamicPrivacyController;
- @Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
- @Mock private KeyguardStateController mKeyguardStateController;
- @Mock private DozeLog mDozeLog;
- @Mock private ShadeLogger mShadeLog;
- @Mock private ShadeHeightLogger mShadeHeightLogger;
- @Mock private CommandQueue mCommandQueue;
- @Mock private VibratorHelper mVibratorHelper;
- @Mock private LatencyTracker mLatencyTracker;
- @Mock private PowerManager mPowerManager;
- @Mock private AccessibilityManager mAccessibilityManager;
- @Mock private MetricsLogger mMetricsLogger;
- @Mock private Resources mResources;
- @Mock private Configuration mConfiguration;
- @Mock private KeyguardClockSwitch mKeyguardClockSwitch;
- @Mock private MediaHierarchyManager mMediaHierarchyManager;
- @Mock private ConversationNotificationManager mConversationNotificationManager;
- @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- @Mock private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
- @Mock private KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
- @Mock private KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
- @Mock private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
- @Mock private KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
- @Mock private KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
- @Mock private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
- @Mock private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
- @Mock private KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
- @Mock private KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
- @Mock private KeyguardClockSwitchController mKeyguardClockSwitchController;
- @Mock private KeyguardStatusViewController mKeyguardStatusViewController;
- @Mock private KeyguardStatusBarViewController mKeyguardStatusBarViewController;
- @Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
- @Mock private NotificationShadeDepthController mNotificationShadeDepthController;
- @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
- @Mock private AuthController mAuthController;
- @Mock private ScrimController mScrimController;
- @Mock private MediaDataManager mMediaDataManager;
- @Mock private AmbientState mAmbientState;
- @Mock private UserManager mUserManager;
- @Mock private UiEventLogger mUiEventLogger;
- @Mock private LockIconViewController mLockIconViewController;
- @Mock private KeyguardMediaController mKeyguardMediaController;
- @Mock private NavigationModeController mNavigationModeController;
- @Mock private NavigationBarController mNavigationBarController;
- @Mock private QuickSettingsController mQsController;
- @Mock private LargeScreenShadeHeaderController mLargeScreenShadeHeaderController;
- @Mock private ContentResolver mContentResolver;
- @Mock private TapAgainViewController mTapAgainViewController;
- @Mock private KeyguardIndicationController mKeyguardIndicationController;
- @Mock private FragmentService mFragmentService;
- @Mock private FragmentHostManager mFragmentHostManager;
- @Mock private NotificationRemoteInputManager mNotificationRemoteInputManager;
- @Mock private RecordingController mRecordingController;
- @Mock private LockscreenGestureLogger mLockscreenGestureLogger;
- @Mock private DumpManager mDumpManager;
- @Mock private InteractionJankMonitor mInteractionJankMonitor;
- @Mock private NotificationsQSContainerController mNotificationsQSContainerController;
- @Mock private QsFrameTranslateController mQsFrameTranslateController;
- @Mock private StatusBarWindowStateController mStatusBarWindowStateController;
- @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
- @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
- @Mock private SysUiState mSysUiState;
- @Mock private NotificationListContainer mNotificationListContainer;
- @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
- @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
- @Mock private ShadeTransitionController mShadeTransitionController;
- @Mock private QS mQs;
- @Mock private QSFragment mQSFragment;
- @Mock private ViewGroup mQsHeader;
- @Mock private ViewParent mViewParent;
- @Mock private ViewTreeObserver mViewTreeObserver;
- @Mock private KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
- @Mock private KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
- @Mock private DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
- @Mock private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
- @Mock private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
- @Mock private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
- @Mock private GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
-
- @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
- @Mock private KeyguardInteractor mKeyguardInteractor;
- @Mock private KeyguardLongPressViewModel mKeyuardLongPressViewModel;
- @Mock private CoroutineDispatcher mMainDispatcher;
- @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
- @Mock private MotionEvent mDownMotionEvent;
- @Captor
- private ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
- mEmptySpaceClickListenerCaptor;
-
- private NotificationPanelViewController.TouchHandler mTouchHandler;
- private ConfigurationController mConfigurationController;
- private SysuiStatusBarStateController mStatusBarStateController;
- private NotificationPanelViewController mNotificationPanelViewController;
- private View.AccessibilityDelegate mAccessibilityDelegate;
- private NotificationsQuickSettingsContainer mNotificationContainerParent;
- private List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
- private Handler mMainHandler;
- private View.OnLayoutChangeListener mLayoutChangeListener;
-
- private final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
- private final Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
- private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
- private final ShadeExpansionStateManager mShadeExpansionStateManager =
- new ShadeExpansionStateManager();
-
- private QuickSettingsController mQuickSettingsController;
- @Mock private Lazy<NotificationPanelViewController> mNotificationPanelViewControllerLazy;
-
- private FragmentHostManager.FragmentListener mFragmentListener;
+public class NotificationPanelViewControllerTest extends NotificationPanelViewControllerBaseTest {
@Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- SystemClock systemClock = new FakeSystemClock();
- mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
- mInteractionJankMonitor, mShadeExpansionStateManager);
-
- KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
- keyguardStatusView.setId(R.id.keyguard_status_view);
+ public void before() {
DejankUtils.setImmediate(true);
-
- when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
- when(mHeadsUpCallback.getContext()).thenReturn(mContext);
- when(mView.getResources()).thenReturn(mResources);
- when(mView.getWidth()).thenReturn(PANEL_WIDTH);
- when(mResources.getConfiguration()).thenReturn(mConfiguration);
- mConfiguration.orientation = ORIENTATION_PORTRAIT;
- when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
- mDisplayMetrics.density = 100;
- when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
- when(mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade))
- .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
- when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
- .thenReturn(10);
- when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
- .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
- when(mView.getContext()).thenReturn(getContext());
- when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
- when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
- when(mView.findViewById(R.id.keyguard_user_switcher_stub)).thenReturn(
- mUserSwitcherStubView);
- when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
- when(mView.findViewById(R.id.notification_stack_scroller))
- .thenReturn(mNotificationStackScrollLayout);
- when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
- when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
- .thenReturn(mHeadsUpCallback);
- when(mKeyguardBottomAreaViewController.getView()).thenReturn(mKeyguardBottomArea);
- when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
- when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class));
- when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
- when(mView.findViewById(R.id.keyguard_status_view))
- .thenReturn(mock(KeyguardStatusView.class));
- mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
- mNotificationContainerParent.addView(keyguardStatusView);
- mNotificationContainerParent.onFinishInflate();
- when(mView.findViewById(R.id.notification_container_parent))
- .thenReturn(mNotificationContainerParent);
- when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
- FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
- mDisplayMetrics);
- when(mKeyguardQsUserSwitchComponentFactory.build(any()))
- .thenReturn(mKeyguardQsUserSwitchComponent);
- when(mKeyguardQsUserSwitchComponent.getKeyguardQsUserSwitchController())
- .thenReturn(mKeyguardQsUserSwitchController);
- when(mKeyguardUserSwitcherComponentFactory.build(any()))
- .thenReturn(mKeyguardUserSwitcherComponent);
- when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController())
- .thenReturn(mKeyguardUserSwitcherController);
- when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
- when(mQs.getView()).thenReturn(mView);
- when(mQSFragment.getView()).thenReturn(mView);
- doAnswer(invocation -> {
- mFragmentListener = invocation.getArgument(1);
- return null;
- }).when(mFragmentHostManager).addTagListener(eq(QS.TAG), any());
- doAnswer((Answer<Void>) invocation -> {
- mTouchHandler = invocation.getArgument(0);
- return null;
- }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class));
-
- NotificationWakeUpCoordinator coordinator =
- new NotificationWakeUpCoordinator(
- mDumpManager,
- mock(HeadsUpManagerPhone.class),
- new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
- mInteractionJankMonitor, mShadeExpansionStateManager),
- mKeyguardBypassController,
- mDozeParameters,
- mScreenOffAnimationController,
- mock(NotificationWakeUpCoordinatorLogger.class));
- mConfigurationController = new ConfigurationControllerImpl(mContext);
- PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
- mContext,
- coordinator,
- mKeyguardBypassController, mHeadsUpManager,
- mock(NotificationRoundnessManager.class),
- mConfigurationController,
- mStatusBarStateController,
- mFalsingManager,
- mShadeExpansionStateManager,
- mLockscreenShadeTransitionController,
- new FalsingCollectorFake(),
- mDumpManager);
- when(mKeyguardStatusViewComponentFactory.build(any()))
- .thenReturn(mKeyguardStatusViewComponent);
- when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
- .thenReturn(mKeyguardClockSwitchController);
- when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
- .thenReturn(mKeyguardStatusViewController);
- when(mKeyguardStatusBarViewComponentFactory.build(any(), any()))
- .thenReturn(mKeyguardStatusBarViewComponent);
- when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
- .thenReturn(mKeyguardStatusBarViewController);
- when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
- .thenReturn(keyguardStatusView);
- when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
- .thenReturn(mUserSwitcherView);
- when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean()))
- .thenReturn(mKeyguardBottomArea);
- when(mNotificationRemoteInputManager.isRemoteInputActive())
- .thenReturn(false);
- when(mInteractionJankMonitor.begin(any(), anyInt()))
- .thenReturn(true);
- when(mInteractionJankMonitor.end(anyInt()))
- .thenReturn(true);
- doAnswer(invocation -> {
- ((Runnable) invocation.getArgument(0)).run();
- return null;
- }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
- doAnswer(invocation -> {
- mLayoutChangeListener = invocation.getArgument(0);
- return null;
- }).when(mView).addOnLayoutChangeListener(any());
-
- when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
- when(mView.getParent()).thenReturn(mViewParent);
- when(mQs.getHeader()).thenReturn(mQsHeader);
- when(mDownMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_DOWN);
- when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
-
- mMainHandler = new Handler(Looper.getMainLooper());
-
- when(mView.requireViewById(R.id.keyguard_long_press))
- .thenReturn(mock(LongPressHandlingView.class));
-
- mNotificationPanelViewController = new NotificationPanelViewController(
- mView,
- mMainHandler,
- mLayoutInflater,
- mFeatureFlags,
- coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
- mFalsingManager, new FalsingCollectorFake(),
- mKeyguardStateController,
- mStatusBarStateController,
- mStatusBarWindowStateController,
- mNotificationShadeWindowController,
- mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper,
- mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
- mMetricsLogger,
- mShadeLog,
- mShadeHeightLogger,
- mConfigurationController,
- () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
- mConversationNotificationManager, mMediaHierarchyManager,
- mStatusBarKeyguardViewManager,
- mGutsManager,
- mNotificationsQSContainerController,
- mNotificationStackScrollLayoutController,
- mKeyguardStatusViewComponentFactory,
- mKeyguardQsUserSwitchComponentFactory,
- mKeyguardUserSwitcherComponentFactory,
- mKeyguardStatusBarViewComponentFactory,
- mLockscreenShadeTransitionController,
- mAuthController,
- mScrimController,
- mUserManager,
- mMediaDataManager,
- mNotificationShadeDepthController,
- mAmbientState,
- mLockIconViewController,
- mKeyguardMediaController,
- mTapAgainViewController,
- mNavigationModeController,
- mNavigationBarController,
- mQsController,
- mFragmentService,
- mContentResolver,
- mRecordingController,
- mLargeScreenShadeHeaderController,
- mScreenOffAnimationController,
- mLockscreenGestureLogger,
- mShadeExpansionStateManager,
- mNotificationRemoteInputManager,
- mSysUIUnfoldComponent,
- mSysUiState,
- () -> mKeyguardBottomAreaViewController,
- mKeyguardUnlockAnimationController,
- mKeyguardIndicationController,
- mNotificationListContainer,
- mNotificationStackSizeCalculator,
- mUnlockedScreenOffAnimationController,
- mShadeTransitionController,
- systemClock,
- mKeyguardBottomAreaViewModel,
- mKeyguardBottomAreaInteractor,
- mAlternateBouncerInteractor,
- mDreamingToLockscreenTransitionViewModel,
- mOccludedToLockscreenTransitionViewModel,
- mLockscreenToDreamingTransitionViewModel,
- mGoneToDreamingTransitionViewModel,
- mLockscreenToOccludedTransitionViewModel,
- mMainDispatcher,
- mKeyguardTransitionInteractor,
- mDumpManager,
- mKeyuardLongPressViewModel,
- mKeyguardInteractor);
- mNotificationPanelViewController.initDependencies(
- mCentralSurfaces,
- null,
- () -> {},
- mNotificationShelfController);
- mNotificationPanelViewController.setTrackingStartedListener(() -> {});
- mNotificationPanelViewController.setOpenCloseListener(
- new NotificationPanelViewController.OpenCloseListener() {
- @Override
- public void onClosingFinished() {}
-
- @Override
- public void onOpenStarted() {}
- });
- mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
- ArgumentCaptor<View.OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
- ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
- verify(mView, atLeast(1)).addOnAttachStateChangeListener(
- onAttachStateChangeListenerArgumentCaptor.capture());
- mOnAttachStateChangeListeners = onAttachStateChangeListenerArgumentCaptor.getAllValues();
-
- ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
- ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
- verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
- mAccessibilityDelegate = accessibilityDelegateArgumentCaptor.getValue();
- mNotificationPanelViewController.getStatusBarStateController()
- .addCallback(mNotificationPanelViewController.getStatusBarStateListener());
- mNotificationPanelViewController
- .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
- verify(mNotificationStackScrollLayoutController)
- .setOnEmptySpaceClickListener(mEmptySpaceClickListenerCaptor.capture());
- verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
- reset(mKeyguardStatusViewController);
-
- when(mNotificationPanelViewControllerLazy.get())
- .thenReturn(mNotificationPanelViewController);
- mQuickSettingsController = new QuickSettingsController(
- mNotificationPanelViewControllerLazy,
- mView,
- mQsFrameTranslateController,
- mShadeTransitionController,
- expansionHandler,
- mNotificationRemoteInputManager,
- mShadeExpansionStateManager,
- mStatusBarKeyguardViewManager,
- mNotificationStackScrollLayoutController,
- mLockscreenShadeTransitionController,
- mNotificationShadeDepthController,
- mLargeScreenShadeHeaderController,
- mStatusBarTouchableRegionManager,
- mKeyguardStateController,
- mKeyguardBypassController,
- mUpdateMonitor,
- mScrimController,
- mMediaDataManager,
- mMediaHierarchyManager,
- mAmbientState,
- mRecordingController,
- mFalsingManager,
- new FalsingCollectorFake(),
- mAccessibilityManager,
- mLockscreenGestureLogger,
- mMetricsLogger,
- mFeatureFlags,
- mInteractionJankMonitor,
- mShadeLog
- );
- }
-
- @After
- public void tearDown() {
- mNotificationPanelViewController.cancelHeightAnimator();
- mMainHandler.removeCallbacksAndMessages(null);
}
@Test
@@ -671,23 +131,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
.isNotEqualTo(-1);
}
- private void setBottomPadding(int stackBottom, int lockIconPadding, int indicationPadding,
- int ambientPadding) {
-
- when(mNotificationStackScrollLayoutController.getTop()).thenReturn(0);
- when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(stackBottom);
- when(mNotificationStackScrollLayoutController.getBottom()).thenReturn(stackBottom);
- when(mLockIconViewController.getTop()).thenReturn((float) (stackBottom - lockIconPadding));
-
- when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
- .thenReturn(indicationPadding);
- mNotificationPanelViewController.loadDimens();
-
- mNotificationPanelViewController.setAmbientIndicationTop(
- /* ambientIndicationTop= */ stackBottom - ambientPadding,
- /* ambientTextVisible= */ true);
- }
-
@Test
@Ignore("b/261472011 - Test appears inconsistent across environments")
public void getVerticalSpaceForLockscreenNotifications_useLockIconBottomPadding_returnsSpaceAvailable() {
@@ -992,68 +435,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
- public void testDisableUserSwitcherAfterEnabling_returnsViewStubToTheViewHierarchy() {
- givenViewAttached();
- when(mResources.getBoolean(
- com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
- updateMultiUserSetting(true);
- clearInvocations(mView);
-
- updateMultiUserSetting(false);
-
- ArgumentCaptor<View> captor = ArgumentCaptor.forClass(View.class);
- verify(mView, atLeastOnce()).addView(captor.capture(), anyInt());
- final View userSwitcherStub = CollectionUtils.find(captor.getAllValues(),
- view -> view.getId() == R.id.keyguard_user_switcher_stub);
- assertThat(userSwitcherStub).isNotNull();
- assertThat(userSwitcherStub).isInstanceOf(ViewStub.class);
- }
-
- @Test
- public void testChangeSmallestScreenWidthAndUserSwitchEnabled_inflatesUserSwitchView() {
- givenViewAttached();
- when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(null);
- updateSmallestScreenWidth(300);
- when(mResources.getBoolean(
- com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
- when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
- when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true);
-
- updateSmallestScreenWidth(800);
-
- verify(mUserSwitcherStubView).inflate();
- }
-
- @Test
- public void testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView_initClock() {
- givenViewAttached();
- when(mResources.getBoolean(
- com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
- when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
- when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
- .thenReturn(false);
-
- mNotificationPanelViewController.onFinishInflate();
-
- verify(mUserSwitcherStubView, never()).inflate();
- verify(mKeyguardStatusViewController, times(3)).displayClock(LARGE, /* animate */ true);
- }
-
- @Test
- public void testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() {
- givenViewAttached();
- when(mResources.getBoolean(
- com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
- when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
- when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
- .thenReturn(false);
-
- mNotificationPanelViewController.reInflateViews();
-
- verify(mUserSwitcherStubView, never()).inflate();
- }
-
- @Test
public void testCanCollapsePanelOnTouch_trueForKeyGuard() {
mStatusBarStateController.setState(KEYGUARD);
@@ -1129,26 +510,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
- public void testDoubleTapRequired_Keyguard() {
- FalsingManager.FalsingTapListener listener = getFalsingTapListener();
- mStatusBarStateController.setState(KEYGUARD);
-
- listener.onAdditionalTapRequired();
-
- verify(mKeyguardIndicationController).showTransientIndication(anyInt());
- }
-
- @Test
- public void testDoubleTapRequired_ShadeLocked() {
- FalsingManager.FalsingTapListener listener = getFalsingTapListener();
- mStatusBarStateController.setState(SHADE_LOCKED);
-
- listener.onAdditionalTapRequired();
-
- verify(mTapAgainViewController).show();
- }
-
- @Test
public void testRotatingToSplitShadeWithQsExpanded_transitionsToShadeLocked() {
mStatusBarStateController.setState(KEYGUARD);
when(mQsController.getExpanded()).thenReturn(true);
@@ -1423,19 +784,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
- public void testOnAttachRefreshStatusBarState() {
- mStatusBarStateController.setState(KEYGUARD);
- when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(false);
- for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
- listener.onViewAttachedToWindow(mView);
- }
- verify(mKeyguardStatusViewController).setKeyguardStatusViewVisibility(
- KEYGUARD/*statusBarState*/,
- false/*keyguardFadingAway*/,
- false/*goingToFullShade*/, SHADE/*oldStatusBarState*/);
- }
-
- @Test
public void getMaxPanelTransitionDistance_expanding_inSplitShade_returnsSplitShadeFullTransitionDistance() {
enableSplitShade(true);
mNotificationPanelViewController.expandWithQs();
@@ -1574,6 +922,38 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
+ @Test
+ public void onSplitShadeChanged_duringShadeExpansion_resetsOverScrollState() {
+ // There was a bug where there was left-over overscroll state after going from split shade
+ // to single shade.
+ // Since on single shade we don't set overscroll values on QS nor Scrim, those values that
+ // were there from split shade were never reset.
+ // To prevent this, we will reset all overscroll state.
+ enableSplitShade(true);
+ reset(mQsController, mScrimController, mNotificationStackScrollLayoutController);
+
+ mNotificationPanelViewController.setOverExpansion(123);
+ verify(mQsController).setOverScrollAmount(123);
+ verify(mScrimController).setNotificationsOverScrollAmount(123);
+ verify(mNotificationStackScrollLayoutController).setOverExpansion(123);
+
+ enableSplitShade(false);
+ verify(mQsController).setOverScrollAmount(0);
+ verify(mScrimController).setNotificationsOverScrollAmount(0);
+ verify(mNotificationStackScrollLayoutController).setOverExpansion(0);
+ }
+
+ @Test
+ public void onSplitShadeChanged_alwaysResetsOverScrollState() {
+ enableSplitShade(true);
+ enableSplitShade(false);
+
+ verify(mQsController, times(2)).setOverScrollAmount(0);
+ verify(mScrimController, times(2)).setNotificationsOverScrollAmount(0);
+ verify(mNotificationStackScrollLayoutController, times(2)).setOverExpansion(0);
+ verify(mNotificationStackScrollLayoutController, times(2)).setOverScrollAmount(0);
+ }
+
/**
* When shade is flinging to close and this fling is not intercepted,
* {@link AmbientState#setIsClosing(boolean)} should be called before
@@ -1635,98 +1015,4 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
mStatusBarStateController.setState(SHADE_LOCKED);
assertThat(mNotificationPanelViewController.isShadeFullyOpen()).isTrue();
}
-
- private static MotionEvent createMotionEvent(int x, int y, int action) {
- return MotionEvent.obtain(
- /* downTime= */ 0, /* eventTime= */ 0, action, x, y, /* metaState= */ 0);
- }
-
- private void triggerPositionClockAndNotifications() {
- mNotificationPanelViewController.onQsSetExpansionHeightCalled(false);
- }
-
- private FalsingManager.FalsingTapListener getFalsingTapListener() {
- for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
- listener.onViewAttachedToWindow(mView);
- }
- assertThat(mFalsingManager.getTapListeners().size()).isEqualTo(1);
- return mFalsingManager.getTapListeners().get(0);
- }
-
- private void givenViewAttached() {
- for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
- listener.onViewAttachedToWindow(mView);
- }
- }
-
- private ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
- ConstraintSet constraintSet = new ConstraintSet();
- constraintSet.clone(mNotificationContainerParent);
- return constraintSet.getConstraint(id).layout;
- }
-
- private void enableSplitShade(boolean enabled) {
- when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled);
- mNotificationPanelViewController.updateResources();
- }
-
- private void updateMultiUserSetting(boolean enabled) {
- when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
- when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
- final ArgumentCaptor<ContentObserver> observerCaptor =
- ArgumentCaptor.forClass(ContentObserver.class);
- verify(mContentResolver)
- .registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
- observerCaptor.getValue().onChange(/* selfChange */ false);
- }
-
- private void updateSmallestScreenWidth(int smallestScreenWidthDp) {
- Configuration configuration = new Configuration();
- configuration.smallestScreenWidthDp = smallestScreenWidthDp;
- mConfigurationController.onConfigurationChanged(configuration);
- }
-
- private void onTouchEvent(MotionEvent ev) {
- mTouchHandler.onTouch(mView, ev);
- }
-
- private void setDozing(boolean dozing, boolean dozingAlwaysOn) {
- when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn);
- mNotificationPanelViewController.setDozing(
- /* dozing= */ dozing,
- /* animate= */ false
- );
- }
-
- private void assertKeyguardStatusViewCentered() {
- mNotificationPanelViewController.updateResources();
- assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isAnyOf(
- ConstraintSet.PARENT_ID, ConstraintSet.UNSET);
- }
-
- private void assertKeyguardStatusViewNotCentered() {
- mNotificationPanelViewController.updateResources();
- assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo(
- R.id.qs_edge_guideline);
- }
-
- private void setIsFullWidth(boolean fullWidth) {
- float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f;
- when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth);
- triggerLayoutChange();
- }
-
- private void triggerLayoutChange() {
- mLayoutChangeListener.onLayoutChange(
- mView,
- /* left= */ 0,
- /* top= */ 0,
- /* right= */ 0,
- /* bottom= */ 0,
- /* oldLeft= */ 0,
- /* oldTop= */ 0,
- /* oldRight= */ 0,
- /* oldBottom= */ 0
- );
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
new file mode 100644
index 000000000000..0c046e93ee20
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+import android.view.ViewStub
+import androidx.test.filters.SmallTest
+import com.android.internal.util.CollectionUtils
+import com.android.keyguard.KeyguardClockSwitch.LARGE
+import com.android.systemui.R
+import com.android.systemui.statusbar.StatusBarState.KEYGUARD
+import com.android.systemui.statusbar.StatusBarState.SHADE
+import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Captor
+import org.mockito.Mockito.atLeastOnce
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@SmallTest
+class NotificationPanelViewControllerWithCoroutinesTest :
+ NotificationPanelViewControllerBaseTest() {
+
+ @Captor private lateinit var viewCaptor: ArgumentCaptor<View>
+
+ override fun getMainDispatcher() = Dispatchers.Main.immediate
+
+ @Test
+ fun testDisableUserSwitcherAfterEnabling_returnsViewStubToTheViewHierarchy() = runTest {
+ launch(Dispatchers.Main.immediate) { givenViewAttached() }
+ advanceUntilIdle()
+
+ whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+ .thenReturn(true)
+ updateMultiUserSetting(true)
+ clearInvocations(mView)
+
+ updateMultiUserSetting(false)
+
+ verify(mView, atLeastOnce()).addView(viewCaptor.capture(), anyInt())
+ val userSwitcherStub =
+ CollectionUtils.find(
+ viewCaptor.getAllValues(),
+ { view -> view.getId() == R.id.keyguard_user_switcher_stub }
+ )
+ assertThat(userSwitcherStub).isNotNull()
+ assertThat(userSwitcherStub).isInstanceOf(ViewStub::class.java)
+ }
+
+ @Test
+ fun testChangeSmallestScreenWidthAndUserSwitchEnabled_inflatesUserSwitchView() = runTest {
+ launch(Dispatchers.Main.immediate) { givenViewAttached() }
+ advanceUntilIdle()
+
+ whenever(mView.findViewById<View>(R.id.keyguard_user_switcher_view)).thenReturn(null)
+ updateSmallestScreenWidth(300)
+ whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+ .thenReturn(true)
+ whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+ .thenReturn(false)
+ whenever(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true)
+
+ updateSmallestScreenWidth(800)
+
+ verify(mUserSwitcherStubView).inflate()
+ }
+
+ @Test
+ fun testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView_initClock() = runTest {
+ launch(Dispatchers.Main.immediate) { givenViewAttached() }
+ advanceUntilIdle()
+
+ whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+ .thenReturn(true)
+ whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+ .thenReturn(false)
+ whenever(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+ .thenReturn(false)
+
+ mNotificationPanelViewController.onFinishInflate()
+
+ verify(mUserSwitcherStubView, never()).inflate()
+ verify(mKeyguardStatusViewController, times(3)).displayClock(LARGE, /* animate */ true)
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() = runTest {
+ launch(Dispatchers.Main.immediate) { givenViewAttached() }
+ advanceUntilIdle()
+
+ whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+ .thenReturn(true)
+ whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+ .thenReturn(false)
+ whenever(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+ .thenReturn(false)
+
+ mNotificationPanelViewController.reInflateViews()
+
+ verify(mUserSwitcherStubView, never()).inflate()
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun testDoubleTapRequired_Keyguard() = runTest {
+ launch(Dispatchers.Main.immediate) {
+ val listener = getFalsingTapListener()
+ mStatusBarStateController.setState(KEYGUARD)
+
+ listener.onAdditionalTapRequired()
+
+ verify(mKeyguardIndicationController).showTransientIndication(anyInt())
+ }
+ advanceUntilIdle()
+ }
+
+ @Test
+ fun testDoubleTapRequired_ShadeLocked() = runTest {
+ launch(Dispatchers.Main.immediate) {
+ val listener = getFalsingTapListener()
+ mStatusBarStateController.setState(SHADE_LOCKED)
+
+ listener.onAdditionalTapRequired()
+
+ verify(mTapAgainViewController).show()
+ }
+ advanceUntilIdle()
+ }
+
+ @Test
+ fun testOnAttachRefreshStatusBarState() = runTest {
+ launch(Dispatchers.Main.immediate) {
+ mStatusBarStateController.setState(KEYGUARD)
+ whenever(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(false)
+ mOnAttachStateChangeListeners.forEach { it.onViewAttachedToWindow(mView) }
+ verify(mKeyguardStatusViewController)
+ .setKeyguardStatusViewVisibility(
+ KEYGUARD /*statusBarState*/,
+ false /*keyguardFadingAway*/,
+ false /*goingToFullShade*/,
+ SHADE /*oldStatusBarState*/
+ )
+ }
+ advanceUntilIdle()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
index c915502ad42e..dfb1bce20ff8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
@@ -12,7 +12,6 @@ import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FeatureFlags
import com.android.systemui.fragments.FragmentHostManager
import com.android.systemui.fragments.FragmentService
import com.android.systemui.navigationbar.NavigationModeController
@@ -40,8 +39,8 @@ import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -68,12 +67,10 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
@Mock
private lateinit var notificationsQSContainer: NotificationsQuickSettingsContainer
@Mock
- private lateinit var largeScreenShadeHeaderController: LargeScreenShadeHeaderController
+ private lateinit var mShadeHeaderController: ShadeHeaderController
@Mock
private lateinit var shadeExpansionStateManager: ShadeExpansionStateManager
@Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
private lateinit var fragmentService: FragmentService
@Mock
private lateinit var fragmentHostManager: FragmentHostManager
@@ -109,9 +106,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
notificationsQSContainer,
navigationModeController,
overviewProxyService,
- largeScreenShadeHeaderController,
+ mShadeHeaderController,
shadeExpansionStateManager,
- featureFlags,
fragmentService,
delayableExecutor
)
@@ -396,9 +392,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
container,
navigationModeController,
overviewProxyService,
- largeScreenShadeHeaderController,
+ mShadeHeaderController,
shadeExpansionStateManager,
- featureFlags,
fragmentService,
delayableExecutor
)
@@ -429,16 +424,16 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
@Test
fun testStartCustomizingWithDuration() {
controller.setCustomizerShowing(true, 100L)
- verify(largeScreenShadeHeaderController).startCustomizingAnimation(true, 100L)
+ verify(mShadeHeaderController).startCustomizingAnimation(true, 100L)
}
@Test
fun testEndCustomizingWithDuration() {
controller.setCustomizerShowing(true, 0L) // Only tracks changes
- reset(largeScreenShadeHeaderController)
+ reset(mShadeHeaderController)
controller.setCustomizerShowing(false, 100L)
- verify(largeScreenShadeHeaderController).startCustomizingAnimation(false, 100L)
+ verify(mShadeHeaderController).startCustomizingAnimation(false, 100L)
}
@Test
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 d229a08ad7c4..315663c39322 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -28,11 +28,12 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.dock.DockManager
-import com.android.systemui.flags.FeatureFlags
import com.android.systemui.keyguard.KeyguardUnlockAnimationController
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
import com.android.systemui.statusbar.LockscreenShadeTransitionController
import com.android.systemui.statusbar.NotificationInsetsController
@@ -47,6 +48,7 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.statusbar.window.StatusBarWindowStateController
import com.android.systemui.util.mockito.any
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.emptyFlow
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -64,50 +66,32 @@ import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@RunWithLooper(setAsMainLooper = true)
class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
- @Mock
- private lateinit var view: NotificationShadeWindowView
- @Mock
- private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
- @Mock
- private lateinit var centralSurfaces: CentralSurfaces
- @Mock
- private lateinit var dockManager: DockManager
- @Mock
- private lateinit var notificationPanelViewController: NotificationPanelViewController
- @Mock
- private lateinit var notificationShadeDepthController: NotificationShadeDepthController
- @Mock
- private lateinit var notificationShadeWindowController: NotificationShadeWindowController
- @Mock
- private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
- @Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
- private lateinit var ambientState: AmbientState
- @Mock
- private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
- @Mock
- private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController
- @Mock
- private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
- @Mock
- private lateinit var statusBarWindowStateController: StatusBarWindowStateController
+ @Mock private lateinit var view: NotificationShadeWindowView
+ @Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
+ @Mock private lateinit var centralSurfaces: CentralSurfaces
+ @Mock private lateinit var dockManager: DockManager
+ @Mock private lateinit var notificationPanelViewController: NotificationPanelViewController
+ @Mock private lateinit var notificationShadeDepthController: NotificationShadeDepthController
+ @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
+ @Mock private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
+ @Mock private lateinit var ambientState: AmbientState
+ @Mock private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
+ @Mock private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController
+ @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+ @Mock private lateinit var statusBarWindowStateController: StatusBarWindowStateController
@Mock
private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController
- @Mock
- private lateinit var lockIconViewController: LockIconViewController
- @Mock
- private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
- @Mock
- private lateinit var pulsingGestureListener: PulsingGestureListener
- @Mock
- private lateinit var notificationInsetsController: NotificationInsetsController
- @Mock
- private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
+ @Mock private lateinit var lockIconViewController: LockIconViewController
+ @Mock private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
+ @Mock private lateinit var pulsingGestureListener: PulsingGestureListener
+ @Mock private lateinit var notificationInsetsController: NotificationInsetsController
+ @Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
@Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
@Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
@Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
@Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
+ @Mock
+ lateinit var primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
private lateinit var interactionEventHandler: InteractionEventHandler
@@ -119,42 +103,44 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this)
whenever(view.bottom).thenReturn(VIEW_BOTTOM)
whenever(view.findViewById<ViewGroup>(R.id.keyguard_bouncer_container))
- .thenReturn(mock(ViewGroup::class.java))
+ .thenReturn(mock(ViewGroup::class.java))
whenever(keyguardBouncerComponentFactory.create(any(ViewGroup::class.java)))
- .thenReturn(keyguardBouncerComponent)
+ .thenReturn(keyguardBouncerComponent)
whenever(keyguardBouncerComponent.securityContainerController)
- .thenReturn(keyguardSecurityContainerController)
- underTest = NotificationShadeWindowViewController(
- lockscreenShadeTransitionController,
- FalsingCollectorFake(),
- sysuiStatusBarStateController,
- dockManager,
- notificationShadeDepthController,
- view,
- notificationPanelViewController,
- ShadeExpansionStateManager(),
- stackScrollLayoutController,
- statusBarKeyguardViewManager,
- statusBarWindowStateController,
- lockIconViewController,
- centralSurfaces,
- notificationShadeWindowController,
- keyguardUnlockAnimationController,
- notificationInsetsController,
- ambientState,
- pulsingGestureListener,
- featureFlags,
- keyguardBouncerViewModel,
- keyguardBouncerComponentFactory,
- alternateBouncerInteractor,
- keyguardTransitionInteractor,
- )
+ .thenReturn(keyguardSecurityContainerController)
+ whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
+ .thenReturn(emptyFlow<TransitionStep>())
+ underTest =
+ NotificationShadeWindowViewController(
+ lockscreenShadeTransitionController,
+ FalsingCollectorFake(),
+ sysuiStatusBarStateController,
+ dockManager,
+ notificationShadeDepthController,
+ view,
+ notificationPanelViewController,
+ ShadeExpansionStateManager(),
+ stackScrollLayoutController,
+ statusBarKeyguardViewManager,
+ statusBarWindowStateController,
+ lockIconViewController,
+ centralSurfaces,
+ notificationShadeWindowController,
+ keyguardUnlockAnimationController,
+ notificationInsetsController,
+ ambientState,
+ pulsingGestureListener,
+ keyguardBouncerViewModel,
+ keyguardBouncerComponentFactory,
+ alternateBouncerInteractor,
+ keyguardTransitionInteractor,
+ primaryBouncerToGoneTransitionViewModel,
+ )
underTest.setupExpandedStatusBar()
- interactionEventHandlerCaptor =
- ArgumentCaptor.forClass(InteractionEventHandler::class.java)
+ interactionEventHandlerCaptor = ArgumentCaptor.forClass(InteractionEventHandler::class.java)
verify(view).setInteractionEventHandler(interactionEventHandlerCaptor.capture())
- interactionEventHandler = interactionEventHandlerCaptor.value
+ interactionEventHandler = interactionEventHandlerCaptor.value
}
// Note: So far, these tests only cover interactions with the status bar view controller. More
@@ -184,14 +170,11 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
@Test
fun handleDispatchTouchEvent_downTouchBelowViewThenAnotherTouch_sendsTouchToSb() {
underTest.setStatusBarViewController(phoneStatusBarViewController)
- val downEvBelow = MotionEvent.obtain(
- 0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0
- )
+ val downEvBelow =
+ MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0)
interactionEventHandler.handleDispatchTouchEvent(downEvBelow)
- val nextEvent = MotionEvent.obtain(
- 0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0
- )
+ val nextEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0)
whenever(phoneStatusBarViewController.sendTouchToView(nextEvent)).thenReturn(true)
val returnVal = interactionEventHandler.handleDispatchTouchEvent(nextEvent)
@@ -293,6 +276,20 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
underTest.keyguardMessageArea
verify(view).findViewById<ViewGroup>(R.id.keyguard_message_area)
}
+
+ @Test
+ fun handleDispatchTouchEvent_statusBarViewControllerOnTouch_returnsTrue() {
+ underTest.setStatusBarViewController(phoneStatusBarViewController)
+
+ // GIVEN the statusBarKeyguardViewManager will handle any touches
+ whenever(statusBarKeyguardViewManager.onTouch(any())).thenReturn(true)
+
+ // WHEN a touch is dispatched
+ val returnVal = interactionEventHandler.handleDispatchTouchEvent(downEv)
+
+ // THEN handleDispatchTouchEvent returns true
+ assertThat(returnVal).isTrue()
+ }
}
private val downEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
index 5e9c2199897d..faa6221b675c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
@@ -25,6 +25,8 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
import android.os.SystemClock;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -40,11 +42,11 @@ import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.dock.DockManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationInsetsController;
@@ -93,7 +95,6 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@Mock private AmbientState mAmbientState;
@Mock private PulsingGestureListener mPulsingGestureListener;
- @Mock private FeatureFlags mFeatureFlags;
@Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
@Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
@Mock private KeyguardBouncerComponent mKeyguardBouncerComponent;
@@ -101,6 +102,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
@Mock private NotificationInsetsController mNotificationInsetsController;
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
@Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+ @Mock private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
@Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
mInteractionEventHandlerCaptor;
@@ -125,6 +127,9 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
when(mDockManager.isDocked()).thenReturn(false);
+ when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition())
+ .thenReturn(emptyFlow());
+
mController = new NotificationShadeWindowViewController(
mLockscreenShadeTransitionController,
new FalsingCollectorFake(),
@@ -144,11 +149,11 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
mNotificationInsetsController,
mAmbientState,
mPulsingGestureListener,
- mFeatureFlags,
mKeyguardBouncerViewModel,
mKeyguardBouncerComponentFactory,
mAlternateBouncerInteractor,
- mKeyguardTransitionInteractor
+ mKeyguardTransitionInteractor,
+ mPrimaryBouncerToGoneTransitionViewModel
);
mController.setupExpandedStatusBar();
mController.setDragDownHelper(mDragDownHelper);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
index c2fca6f2120b..15b84238dd19 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
@@ -16,6 +16,13 @@
package com.android.systemui.shade;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_POINTER_DOWN;
+import static android.view.MotionEvent.ACTION_UP;
+import static android.view.MotionEvent.BUTTON_SECONDARY;
+import static android.view.MotionEvent.BUTTON_STYLUS_PRIMARY;
+
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
@@ -25,6 +32,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -70,13 +78,10 @@ import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
@@ -86,9 +91,12 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.List;
+
import dagger.Lazy;
@SmallTest
@@ -96,7 +104,14 @@ import dagger.Lazy;
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class QuickSettingsControllerTest extends SysuiTestCase {
- private static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
+ private static final float QS_FRAME_START_X = 0f;
+ private static final int QS_FRAME_WIDTH = 1000;
+ private static final int QS_FRAME_TOP = 0;
+ private static final int QS_FRAME_BOTTOM = 1000;
+ private static final int DEFAULT_HEIGHT = 1000;
+ // In split shade min = max
+ private static final int DEFAULT_MIN_HEIGHT_SPLIT_SHADE = DEFAULT_HEIGHT;
+ private static final int DEFAULT_MIN_HEIGHT = 300;
private QuickSettingsController mQsController;
@@ -105,7 +120,6 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
@Mock private KeyguardStatusBarView mKeyguardStatusBar;
@Mock private QS mQs;
@Mock private QSFragment mQSFragment;
-
@Mock private Lazy<NotificationPanelViewController> mPanelViewControllerLazy;
@Mock private NotificationPanelViewController mNotificationPanelViewController;
@Mock private NotificationPanelView mPanelView;
@@ -119,7 +133,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
@Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
@Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
@Mock private NotificationShadeDepthController mNotificationShadeDepthController;
- @Mock private LargeScreenShadeHeaderController mLargeScreenShadeHeaderController;
+ @Mock private ShadeHeaderController mShadeHeaderController;
@Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private KeyguardBypassController mKeyguardBypassController;
@@ -137,11 +151,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
@Mock private FeatureFlags mFeatureFlags;
@Mock private InteractionJankMonitor mInteractionJankMonitor;
@Mock private ShadeLogger mShadeLogger;
-
@Mock private DumpManager mDumpManager;
- @Mock private DozeParameters mDozeParameters;
- @Mock private ScreenOffAnimationController mScreenOffAnimationController;
- @Mock private HeadsUpManagerPhone mHeadsUpManager;
@Mock private UiEventLogger mUiEventLogger;
private SysuiStatusBarStateController mStatusBarStateController;
@@ -164,11 +174,19 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
keyguardStatusView.setId(R.id.keyguard_status_view);
+ when(mResources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_qs_transition_distance)).thenReturn(DEFAULT_HEIGHT);
when(mPanelView.getResources()).thenReturn(mResources);
when(mPanelView.getContext()).thenReturn(getContext());
when(mPanelView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
when(mPanelView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
+ when(mQsFrame.getX()).thenReturn(QS_FRAME_START_X);
+ when(mQsFrame.getWidth()).thenReturn(QS_FRAME_WIDTH);
+ when(mQsHeader.getTop()).thenReturn(QS_FRAME_TOP);
+ when(mQsHeader.getBottom()).thenReturn(QS_FRAME_BOTTOM);
+ when(mPanelView.getY()).thenReturn((float) QS_FRAME_TOP);
+ when(mPanelView.getHeight()).thenReturn(QS_FRAME_BOTTOM);
when(mPanelView.findViewById(R.id.keyguard_status_view))
.thenReturn(mock(KeyguardStatusView.class));
when(mQs.getView()).thenReturn(mPanelView);
@@ -204,7 +222,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
mNotificationStackScrollLayoutController,
mLockscreenShadeTransitionController,
mNotificationShadeDepthController,
- mLargeScreenShadeHeaderController,
+ mShadeHeaderController,
mStatusBarTouchableRegionManager,
mKeyguardStateController,
mKeyguardBypassController,
@@ -229,21 +247,10 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
@After
public void tearDown() {
- mNotificationPanelViewController.cancelHeightAnimator();
mMainHandler.removeCallbacksAndMessages(null);
}
@Test
- public void testOnTouchEvent_isConflictingExpansionGestureSet() {
- assertThat(mQsController.isConflictingExpansionGesture()).isFalse();
- mShadeExpansionStateManager.onPanelExpansionChanged(1f, true, false, 0f);
- mQsController.handleTouch(MotionEvent.obtain(0L /* downTime */,
- 0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
- 0 /* metaState */), false, false);
- assertThat(mQsController.isConflictingExpansionGesture()).isTrue();
- }
-
- @Test
public void testCloseQsSideEffects() {
enableSplitShade(true);
mQsController.setExpandImmediate(true);
@@ -259,18 +266,18 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
mStatusBarStateController.setState(SHADE);
when(mResources.getBoolean(R.bool.config_use_large_screen_shade_header)).thenReturn(true);
mQsController.updateResources();
- verify(mLargeScreenShadeHeaderController).setLargeScreenActive(true);
+ verify(mShadeHeaderController).setLargeScreenActive(true);
when(mResources.getBoolean(R.bool.config_use_large_screen_shade_header)).thenReturn(false);
mQsController.updateResources();
- verify(mLargeScreenShadeHeaderController).setLargeScreenActive(false);
+ verify(mShadeHeaderController).setLargeScreenActive(false);
}
@Test
public void testPanelStaysOpenWhenClosingQs() {
mShadeExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 1,
/* expanded= */ true, /* tracking= */ false, /* dragDownPxAmount= */ 0);
- mNotificationPanelViewController.setExpandedFraction(1f);
+ mQsController.setShadeExpandedHeight(1);
float shadeExpandedHeight = mQsController.getShadeExpandedHeight();
mQsController.animateCloseQs(false);
@@ -281,16 +288,12 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
@Test
public void interceptTouchEvent_withinQs_shadeExpanded_startsQsTracking() {
mQsController.setQs(mQs);
- when(mQsFrame.getX()).thenReturn(0f);
- when(mQsFrame.getWidth()).thenReturn(1000);
- when(mQsHeader.getTop()).thenReturn(0);
- when(mQsHeader.getBottom()).thenReturn(1000);
mQsController.setShadeExpandedHeight(1f);
mQsController.onIntercept(
- createMotionEvent(0, 0, MotionEvent.ACTION_DOWN));
+ createMotionEvent(0, 0, ACTION_DOWN));
mQsController.onIntercept(
- createMotionEvent(0, 500, MotionEvent.ACTION_MOVE));
+ createMotionEvent(0, 500, ACTION_MOVE));
assertThat(mQsController.isTracking()).isTrue();
}
@@ -299,21 +302,124 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
public void interceptTouchEvent_withinQs_shadeExpanded_inSplitShade_doesNotStartQsTracking() {
enableSplitShade(true);
mQsController.setQs(mQs);
- when(mQsFrame.getX()).thenReturn(0f);
- when(mQsFrame.getWidth()).thenReturn(1000);
- when(mQsHeader.getTop()).thenReturn(0);
- when(mQsHeader.getBottom()).thenReturn(1000);
mQsController.setShadeExpandedHeight(1f);
mQsController.onIntercept(
- createMotionEvent(0, 0, MotionEvent.ACTION_DOWN));
+ createMotionEvent(0, 0, ACTION_DOWN));
mQsController.onIntercept(
- createMotionEvent(0, 500, MotionEvent.ACTION_MOVE));
+ createMotionEvent(0, 500, ACTION_MOVE));
+
+ assertThat(mQsController.isTracking()).isFalse();
+ }
+ @Test
+ public void interceptTouch_downBetweenFullyCollapsedAndExpanded() {
+ mQsController.setQs(mQs);
+ when(mQs.getDesiredHeight()).thenReturn(QS_FRAME_BOTTOM);
+ mQsController.onHeightChanged();
+ mQsController.setExpansionHeight(QS_FRAME_BOTTOM / 2f);
+
+ assertThat(mQsController.onIntercept(
+ createMotionEvent(0, QS_FRAME_BOTTOM / 2, ACTION_DOWN))).isTrue();
+ }
+
+ @Test
+ public void onTouch_moveActionSetsCorrectExpansionHeight() {
+ mQsController.setQs(mQs);
+ when(mQs.getDesiredHeight()).thenReturn(QS_FRAME_BOTTOM);
+ mQsController.onHeightChanged();
+ mQsController.setExpansionHeight(QS_FRAME_BOTTOM / 2f);
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_BOTTOM / 4, ACTION_DOWN), false, false);
+ assertThat(mQsController.isTracking()).isTrue();
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_BOTTOM / 4 + 1, ACTION_MOVE), false, false);
+
+ assertThat(mQsController.getExpansionHeight()).isEqualTo(QS_FRAME_BOTTOM / 2 + 1);
+ }
+
+ @Test
+ public void handleTouch_downActionInQsArea() {
+ mQsController.setQs(mQs);
+ mQsController.setBarState(SHADE);
+ mQsController.onPanelExpansionChanged(
+ new ShadeExpansionChangeEvent(
+ 0.5f,
+ true,
+ true,
+ 0
+ ));
+ MotionEvent event =
+ createMotionEvent(QS_FRAME_WIDTH / 2, QS_FRAME_BOTTOM / 2, ACTION_DOWN);
+ mQsController.handleTouch(event, false, false);
+
+ assertThat(mQsController.isTracking()).isTrue();
+ assertThat(mQsController.getInitialTouchY()).isEqualTo(QS_FRAME_BOTTOM / 2);
+ }
+
+ @Test
+ public void handleTouch_qsTouchedWhileCollapsingDisablesTracking() {
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_BOTTOM, ACTION_DOWN), false, false);
+ mQsController.setLastShadeFlingWasExpanding(false);
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_BOTTOM / 2, ACTION_MOVE), false, true);
+ MotionEvent secondTouch = createMotionEvent(0, QS_FRAME_TOP, ACTION_DOWN);
+ mQsController.handleTouch(secondTouch, false, true);
assertThat(mQsController.isTracking()).isFalse();
}
@Test
+ public void handleTouch_qsTouchedWhileExpanding() {
+ mQsController.setQs(mQs);
+ mQsController.handleTouch(
+ createMotionEvent(100, 100, ACTION_DOWN), false, false);
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_BOTTOM / 2, ACTION_MOVE), false, false);
+ mQsController.setLastShadeFlingWasExpanding(true);
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_TOP, ACTION_DOWN), false, false);
+ assertThat(mQsController.isTracking()).isTrue();
+ }
+
+ @Test
+ public void handleTouch_isConflictingExpansionGestureSet() {
+ assertThat(mQsController.isConflictingExpansionGesture()).isFalse();
+ mShadeExpansionStateManager.onPanelExpansionChanged(1f, true, false, 0f);
+ mQsController.handleTouch(MotionEvent.obtain(0L /* downTime */,
+ 0L /* eventTime */, ACTION_DOWN, 0f /* x */, 0f /* y */,
+ 0 /* metaState */), false, false);
+ assertThat(mQsController.isConflictingExpansionGesture()).isTrue();
+ }
+
+ @Test
+ public void handleTouch_isConflictingExpansionGestureSet_cancel() {
+ mShadeExpansionStateManager.onPanelExpansionChanged(1f, true, false, 0f);
+ mQsController.handleTouch(createMotionEvent(0, 0, ACTION_DOWN), false, false);
+ assertThat(mQsController.isConflictingExpansionGesture()).isTrue();
+ mQsController.handleTouch(createMotionEvent(0, 0, ACTION_UP), true, true);
+ assertThat(mQsController.isConflictingExpansionGesture()).isFalse();
+ }
+
+ @Test
+ public void handleTouch_twoFingerExpandPossibleConditions() {
+ assertThat(mQsController.isTwoFingerExpandPossible()).isFalse();
+ mQsController.handleTouch(createMotionEvent(0, 0, ACTION_DOWN), true, false);
+ assertThat(mQsController.isTwoFingerExpandPossible()).isTrue();
+ }
+
+ @Test
+ public void handleTouch_twoFingerDrag() {
+ mQsController.setQs(mQs);
+ mQsController.setStatusBarMinHeight(1);
+ mQsController.setTwoFingerExpandPossible(true);
+ mQsController.handleTouch(
+ createMultitouchMotionEvent(ACTION_POINTER_DOWN), false, false);
+ assertThat(mQsController.isExpandImmediate()).isTrue();
+ verify(mQs).setListening(true);
+ }
+
+ @Test
public void onQsFragmentAttached_fullWidth_setsFullWidthTrueOnQS() {
setIsFullWidth(true);
mFragmentListener.onFragmentViewCreated(QS.TAG, mQSFragment);
@@ -330,19 +436,6 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
}
@Test
- public void getMaxPanelTransitionDistance_inSplitShade_withHeadsUp_returnsBiggerValue() {
- enableSplitShade(true);
- mNotificationPanelViewController.expandWithQs();
- when(mHeadsUpManager.isTrackingHeadsUp()).thenReturn(true);
-
- mNotificationPanelViewController.setHeadsUpDraggingStartingHeight(
- SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
-
- assertThat(mQsController.calculatePanelHeightExpanded(0))
- .isGreaterThan(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
- }
-
- @Test
public void setQsExpansion_lockscreenShadeTransitionInProgress_usesLockscreenSquishiness() {
float squishinessFraction = 0.456f;
mQsController.setQs(mQs);
@@ -379,6 +472,21 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
}
@Test
+ public void updateExpansion_expandImmediateOrAlreadyExpanded_usesFullSquishiness() {
+ mQsController.setQs(mQs);
+ when(mQs.getDesiredHeight()).thenReturn(100);
+ mQsController.onHeightChanged();
+
+ mQsController.setExpandImmediate(true);
+ mQsController.setExpanded(false);
+ mQsController.updateExpansion();
+ mQsController.setExpandImmediate(false);
+ mQsController.setExpanded(true);
+ mQsController.updateExpansion();
+ verify(mQs, times(2)).setQsExpansion(0, 0, 0, 1);
+ }
+
+ @Test
public void shadeExpanded_onKeyguard() {
mStatusBarStateController.setState(KEYGUARD);
// set maxQsExpansion in NPVC
@@ -393,14 +501,144 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
assertThat(mQsController.computeExpansionFraction()).isEqualTo(1f);
}
+ @Test
+ public void handleTouch_splitShadeAndtouchXOutsideQs() {
+ enableSplitShade(true);
+
+ assertThat(mQsController.handleTouch(createMotionEvent(
+ QS_FRAME_WIDTH + 1, QS_FRAME_BOTTOM - 1, ACTION_DOWN),
+ false, false)).isFalse();
+ }
+
+ @Test
+ public void isOpenQsEvent_twoFingerDrag() {
+ assertThat(mQsController.isOpenQsEvent(
+ createMultitouchMotionEvent(ACTION_POINTER_DOWN))).isTrue();
+ }
+
+ @Test
+ public void isOpenQsEvent_stylusButtonClickDrag() {
+ MotionEvent event = createMotionEvent(0, 0, ACTION_DOWN);
+ event.setButtonState(BUTTON_STYLUS_PRIMARY);
+
+ assertThat(mQsController.isOpenQsEvent(event)).isTrue();
+ }
+
+ @Test
+ public void isOpenQsEvent_mouseButtonClickDrag() {
+ MotionEvent event = createMotionEvent(0, 0, ACTION_DOWN);
+ event.setButtonState(BUTTON_SECONDARY);
+
+ assertThat(mQsController.isOpenQsEvent(event)).isTrue();
+ }
+
+ @Test
+ public void shadeClosed_onLockscreen_inSplitShade_setsQsNotVisible() {
+ mQsController.setQs(mQs);
+ enableSplitShade(true);
+ lockScreen();
+
+ closeLockedQS();
+
+ assertQsVisible(false);
+ }
+
+ @Test
+ public void shadeOpened_onLockscreen_inSplitShade_setsQsVisible() {
+ mQsController.setQs(mQs);
+ enableSplitShade(true);
+ lockScreen();
+
+ openLockedQS();
+
+ assertQsVisible(true);
+ }
+
+ @Test
+ public void shadeClosed_onLockscreen_inSingleShade_setsQsNotVisible() {
+ mQsController.setQs(mQs);
+ enableSplitShade(false);
+ lockScreen();
+
+ closeLockedQS();
+
+ verify(mQs).setQsVisible(false);
+ }
+
+ @Test
+ public void shadeOpened_onLockscreen_inSingleShade_setsQsVisible() {
+ mQsController.setQs(mQs);
+ enableSplitShade(false);
+ lockScreen();
+
+ openLockedQS();
+
+ verify(mQs).setQsVisible(true);
+ }
+
+ private void lockScreen() {
+ mQsController.setBarState(KEYGUARD);
+ }
+
+ private void openLockedQS() {
+ when(mLockscreenShadeTransitionController.getQSDragProgress())
+ .thenReturn((float) DEFAULT_HEIGHT);
+ mLockscreenShadeTransitionCallback.setTransitionToFullShadeAmount(
+ /* pxAmount= */ DEFAULT_HEIGHT,
+ /* animate=*/ false,
+ /* delay= */ 0
+ );
+ }
+
+ private void closeLockedQS() {
+ when(mLockscreenShadeTransitionController.getQSDragProgress()).thenReturn(0f);
+ mLockscreenShadeTransitionCallback.setTransitionToFullShadeAmount(
+ /* pxAmount= */ 0,
+ /* animate=*/ false,
+ /* delay= */ 0
+ );
+ }
+
+ private void setSplitShadeHeightProperties() {
+ // In split shade, min = max
+ when(mQs.getQsMinExpansionHeight()).thenReturn(DEFAULT_MIN_HEIGHT_SPLIT_SHADE);
+ when(mQs.getDesiredHeight()).thenReturn(DEFAULT_HEIGHT);
+ mQsController.updateMinHeight();
+ mQsController.onHeightChanged();
+ }
+
+ private void setDefaultHeightProperties() {
+ when(mQs.getQsMinExpansionHeight()).thenReturn(DEFAULT_MIN_HEIGHT);
+ when(mQs.getDesiredHeight()).thenReturn(DEFAULT_HEIGHT);
+ mQsController.updateMinHeight();
+ mQsController.onHeightChanged();
+ }
+
private static MotionEvent createMotionEvent(int x, int y, int action) {
- return MotionEvent.obtain(
- /* downTime= */ 0, /* eventTime= */ 0, action, x, y, /* metaState= */ 0);
+ return MotionEvent.obtain(0, 0, action, x, y, 0);
+ }
+
+ // Creates an empty multitouch event for now
+ private static MotionEvent createMultitouchMotionEvent(int action) {
+ return MotionEvent.obtain(0, 0, action, 2,
+ new MotionEvent.PointerProperties[] {
+ new MotionEvent.PointerProperties(),
+ new MotionEvent.PointerProperties()
+ },
+ new MotionEvent.PointerCoords[] {
+ new MotionEvent.PointerCoords(),
+ new MotionEvent.PointerCoords()
+ }, 0, 0, 0, 0, 0, 0, 0, 0);
}
private void enableSplitShade(boolean enabled) {
when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled);
mQsController.updateResources();
+ if (enabled) {
+ setSplitShadeHeightProperties();
+ } else {
+ setDefaultHeightProperties();
+ }
}
private void setIsFullWidth(boolean fullWidth) {
@@ -412,4 +650,12 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
int oldMaxHeight = mQsController.updateHeightsOnShadeLayoutChange();
mQsController.handleShadeLayoutChanged(oldMaxHeight);
}
+
+ private void assertQsVisible(boolean visible) {
+ ArgumentCaptor<Boolean> visibilityCaptor = ArgumentCaptor.forClass(Boolean.class);
+ verify(mQs, atLeastOnce()).setQsVisible(visibilityCaptor.capture());
+ List<Boolean> allVisibilities = visibilityCaptor.getAllValues();
+ boolean lastVisibility = allVisibilities.get(allVisibilities.size() - 1);
+ assertThat(lastVisibility).isEqualTo(visible);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
index ee5f61c835da..d5308298202d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.systemui.shade
+import android.animation.Animator
+import android.app.StatusBarManager
import android.content.Context
import android.content.res.Resources
import android.content.res.XmlResourceParser
@@ -39,16 +40,13 @@ import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.qs.ChipVisibilityListener
import com.android.systemui.qs.HeaderPrivacyIconsController
import com.android.systemui.qs.carrier.QSCarrierGroup
import com.android.systemui.qs.carrier.QSCarrierGroupController
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.HEADER_TRANSITION_ID
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.LARGE_SCREEN_HEADER_CONSTRAINT
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.QS_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.QS_HEADER_CONSTRAINT
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.phone.StatusIconContainer
@@ -68,136 +66,106 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Answers
import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers
+import org.mockito.ArgumentMatchers.anyFloat
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
-import org.mockito.Mockito.anyBoolean
-import org.mockito.Mockito.anyFloat
-import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.clearInvocations
-import org.mockito.Mockito.inOrder
-import org.mockito.Mockito.never
+import org.mockito.Mockito.mock
import org.mockito.Mockito.reset
-import org.mockito.Mockito.same
-import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
-import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
+import org.mockito.junit.MockitoJUnit
private val EMPTY_CHANGES = ConstraintsChanges()
-/**
- * Tests for [LargeScreenShadeHeaderController] when [Flags.COMBINED_QS_HEADERS] is `true`.
- *
- * Once that flag is removed, this class will be combined with
- * [LargeScreenShadeHeaderControllerTest].
- */
@SmallTest
@RunWith(AndroidTestingRunner::class)
-class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
-
- @Mock
- private lateinit var statusIcons: StatusIconContainer
- @Mock
- private lateinit var statusBarIconController: StatusBarIconController
- @Mock
- private lateinit var iconManagerFactory: StatusBarIconController.TintedIconManager.Factory
- @Mock
- private lateinit var iconManager: StatusBarIconController.TintedIconManager
- @Mock
- private lateinit var qsCarrierGroupController: QSCarrierGroupController
- @Mock
- private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
- @Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
- private lateinit var clock: Clock
- @Mock
- private lateinit var date: VariableDateView
- @Mock
- private lateinit var carrierGroup: QSCarrierGroup
- @Mock
- private lateinit var batteryMeterView: BatteryMeterView
- @Mock
- private lateinit var batteryMeterViewController: BatteryMeterViewController
- @Mock
- private lateinit var privacyIconsController: HeaderPrivacyIconsController
- @Mock
- private lateinit var insetsProvider: StatusBarContentInsetsProvider
- @Mock
- private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory
- @Mock
- private lateinit var variableDateViewController: VariableDateViewController
- @Mock
- private lateinit var dumpManager: DumpManager
+class ShadeHeaderControllerTest : SysuiTestCase() {
+
+ @Mock(answer = Answers.RETURNS_MOCKS) private lateinit var view: MotionLayout
+ @Mock private lateinit var statusIcons: StatusIconContainer
+ @Mock private lateinit var statusBarIconController: StatusBarIconController
+ @Mock private lateinit var iconManagerFactory: StatusBarIconController.TintedIconManager.Factory
+ @Mock private lateinit var iconManager: StatusBarIconController.TintedIconManager
+ @Mock private lateinit var qsCarrierGroupController: QSCarrierGroupController
+ @Mock private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
+ @Mock private lateinit var clock: Clock
+ @Mock private lateinit var date: VariableDateView
+ @Mock private lateinit var carrierGroup: QSCarrierGroup
+ @Mock private lateinit var batteryMeterView: BatteryMeterView
+ @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
+ @Mock private lateinit var privacyIconsController: HeaderPrivacyIconsController
+ @Mock private lateinit var insetsProvider: StatusBarContentInsetsProvider
+ @Mock private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory
+ @Mock private lateinit var variableDateViewController: VariableDateViewController
+ @Mock private lateinit var dumpManager: DumpManager
@Mock
private lateinit var combinedShadeHeadersConstraintManager:
CombinedShadeHeadersConstraintManager
- @Mock
- private lateinit var mockedContext: Context
+ @Mock private lateinit var mockedContext: Context
private lateinit var viewContext: Context
- @Mock(answer = Answers.RETURNS_MOCKS)
- private lateinit var view: MotionLayout
- @Mock
- private lateinit var qqsConstraints: ConstraintSet
- @Mock
- private lateinit var qsConstraints: ConstraintSet
- @Mock
- private lateinit var largeScreenConstraints: ConstraintSet
+ @Mock private lateinit var qqsConstraints: ConstraintSet
+ @Mock private lateinit var qsConstraints: ConstraintSet
+ @Mock private lateinit var largeScreenConstraints: ConstraintSet
+
@Mock private lateinit var demoModeController: DemoModeController
@Mock private lateinit var qsBatteryModeController: QsBatteryModeController
- @JvmField @Rule
- val mockitoRule = MockitoJUnit.rule()
+ @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
var viewVisibility = View.GONE
+ var viewAlpha = 1f
- private lateinit var controller: LargeScreenShadeHeaderController
+ private lateinit var shadeHeaderController: ShadeHeaderController
private lateinit var carrierIconSlots: List<String>
private val configurationController = FakeConfigurationController()
- private lateinit var demoModeControllerCapture: ArgumentCaptor<DemoMode>
+ @Captor private lateinit var demoModeControllerCapture: ArgumentCaptor<DemoMode>
@Before
- fun setUp() {
- demoModeControllerCapture = argumentCaptor<DemoMode>()
+ fun setup() {
whenever<Clock>(view.findViewById(R.id.clock)).thenReturn(clock)
whenever(clock.context).thenReturn(mockedContext)
whenever<TextView>(view.findViewById(R.id.date)).thenReturn(date)
whenever(date.context).thenReturn(mockedContext)
- whenever(variableDateViewControllerFactory.create(any()))
- .thenReturn(variableDateViewController)
whenever<QSCarrierGroup>(view.findViewById(R.id.carrier_group)).thenReturn(carrierGroup)
+
whenever<BatteryMeterView>(view.findViewById(R.id.batteryRemainingIcon))
.thenReturn(batteryMeterView)
whenever<StatusIconContainer>(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons)
- whenever(statusIcons.context).thenReturn(context)
+ viewContext = Mockito.spy(context)
+ whenever(view.context).thenReturn(viewContext)
+ whenever(view.resources).thenReturn(context.resources)
+ whenever(statusIcons.context).thenReturn(context)
whenever(qsCarrierGroupControllerBuilder.setQSCarrierGroup(any()))
.thenReturn(qsCarrierGroupControllerBuilder)
whenever(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
-
- viewContext = spy(context)
- whenever(view.context).thenReturn(viewContext)
- whenever(view.resources).thenReturn(context.resources)
- whenever(view.setVisibility(ArgumentMatchers.anyInt())).then {
+ whenever(view.setVisibility(anyInt())).then {
viewVisibility = it.arguments[0] as Int
null
}
whenever(view.visibility).thenAnswer { _ -> viewVisibility }
- whenever(view.alpha).thenReturn(1f)
- whenever(iconManagerFactory.create(any(), any())).thenReturn(iconManager)
+ whenever(view.setAlpha(anyFloat())).then {
+ viewAlpha = it.arguments[0] as Float
+ null
+ }
+ whenever(view.alpha).thenAnswer { _ -> viewAlpha }
- whenever(featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)).thenReturn(true)
+ whenever(variableDateViewControllerFactory.create(any()))
+ .thenReturn(variableDateViewController)
+ whenever(iconManagerFactory.create(any(), any())).thenReturn(iconManager)
setUpDefaultInsets()
setUpMotionLayout(view)
- controller = LargeScreenShadeHeaderController(
+ shadeHeaderController =
+ ShadeHeaderController(
view,
statusBarIconController,
iconManagerFactory,
@@ -207,16 +175,171 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
variableDateViewControllerFactory,
batteryMeterViewController,
dumpManager,
- featureFlags,
qsCarrierGroupControllerBuilder,
combinedShadeHeadersConstraintManager,
demoModeController,
qsBatteryModeController,
- )
+ )
whenever(view.isAttachedToWindow).thenReturn(true)
- controller.init()
- carrierIconSlots = listOf(
- context.getString(com.android.internal.R.string.status_bar_mobile))
+ shadeHeaderController.init()
+ carrierIconSlots =
+ listOf(context.getString(com.android.internal.R.string.status_bar_mobile))
+ }
+
+ @Test
+ fun updateListeners_registersWhenVisible() {
+ makeShadeVisible()
+ verify(qsCarrierGroupController).setListening(true)
+ verify(statusBarIconController).addIconGroup(any())
+ }
+
+ @Test
+ fun statusIconsAddedWhenAttached() {
+ verify(statusBarIconController).addIconGroup(any())
+ }
+
+ @Test
+ fun statusIconsRemovedWhenDettached() {
+ shadeHeaderController.simulateViewDetached()
+ verify(statusBarIconController).removeIconGroup(any())
+ }
+
+ @Test
+ fun shadeExpandedFraction_updatesAlpha() {
+ makeShadeVisible()
+ shadeHeaderController.shadeExpandedFraction = 0.5f
+ verify(view).setAlpha(ShadeInterpolation.getContentAlpha(0.5f))
+ }
+
+ @Test
+ fun singleCarrier_enablesCarrierIconsInStatusIcons() {
+ whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(true)
+
+ makeShadeVisible()
+
+ verify(statusIcons).removeIgnoredSlots(carrierIconSlots)
+ }
+
+ @Test
+ fun dualCarrier_disablesCarrierIconsInStatusIcons() {
+ whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(false)
+
+ makeShadeVisible()
+
+ verify(statusIcons).addIgnoredSlots(carrierIconSlots)
+ }
+
+ @Test
+ fun disableQS_notDisabled_visible() {
+ makeShadeVisible()
+ shadeHeaderController.disable(0, 0, false)
+
+ assertThat(viewVisibility).isEqualTo(View.VISIBLE)
+ }
+
+ @Test
+ fun disableQS_disabled_gone() {
+ makeShadeVisible()
+ shadeHeaderController.disable(0, StatusBarManager.DISABLE2_QUICK_SETTINGS, false)
+
+ assertThat(viewVisibility).isEqualTo(View.GONE)
+ }
+
+ private fun makeShadeVisible() {
+ shadeHeaderController.largeScreenActive = true
+ shadeHeaderController.qsVisible = true
+ }
+
+ @Test
+ fun updateConfig_changesFontStyle() {
+ configurationController.notifyDensityOrFontScaleChanged()
+
+ verify(clock).setTextAppearance(R.style.TextAppearance_QS_Status)
+ verify(date).setTextAppearance(R.style.TextAppearance_QS_Status)
+ verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status_Carriers)
+ }
+
+ @Test
+ fun animateOutOnStartCustomizing() {
+ val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
+ val duration = 1000L
+ whenever(view.animate()).thenReturn(animator)
+
+ shadeHeaderController.startCustomizingAnimation(show = true, duration)
+
+ verify(animator).setDuration(duration)
+ verify(animator).alpha(0f)
+ verify(animator).setInterpolator(Interpolators.ALPHA_OUT)
+ verify(animator).start()
+ }
+
+ @Test
+ fun animateInOnEndCustomizing() {
+ val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
+ val duration = 1000L
+ whenever(view.animate()).thenReturn(animator)
+
+ shadeHeaderController.startCustomizingAnimation(show = false, duration)
+
+ verify(animator).setDuration(duration)
+ verify(animator).alpha(1f)
+ verify(animator).setInterpolator(Interpolators.ALPHA_IN)
+ verify(animator).start()
+ }
+
+ @Test
+ fun customizerAnimatorChangesViewVisibility() {
+ makeShadeVisible()
+
+ val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
+ val duration = 1000L
+ whenever(view.animate()).thenReturn(animator)
+ val listenerCaptor = argumentCaptor<Animator.AnimatorListener>()
+
+ shadeHeaderController.startCustomizingAnimation(show = true, duration)
+ verify(animator).setListener(capture(listenerCaptor))
+ // Start and end the animation
+ listenerCaptor.value.onAnimationStart(mock())
+ listenerCaptor.value.onAnimationEnd(mock())
+ assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
+
+ reset(animator)
+ shadeHeaderController.startCustomizingAnimation(show = false, duration)
+ verify(animator).setListener(capture(listenerCaptor))
+ // Start and end the animation
+ listenerCaptor.value.onAnimationStart(mock())
+ listenerCaptor.value.onAnimationEnd(mock())
+ assertThat(viewVisibility).isEqualTo(View.VISIBLE)
+ }
+
+ @Test
+ fun animatorListenersClearedAtEnd() {
+ val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
+ whenever(view.animate()).thenReturn(animator)
+
+ shadeHeaderController.startCustomizingAnimation(show = true, 0L)
+ val listenerCaptor = argumentCaptor<Animator.AnimatorListener>()
+ verify(animator).setListener(capture(listenerCaptor))
+
+ listenerCaptor.value.onAnimationEnd(mock())
+ verify(animator).setListener(null)
+ }
+
+ @Test
+ fun demoMode_attachDemoMode() {
+ val cb = argumentCaptor<DemoMode>()
+ verify(demoModeController).addCallback(capture(cb))
+ cb.value.onDemoModeStarted()
+ verify(clock).onDemoModeStarted()
+ }
+
+ @Test
+ fun demoMode_detachDemoMode() {
+ shadeHeaderController.simulateViewDetached()
+ val cb = argumentCaptor<DemoMode>()
+ verify(demoModeController).removeCallback(capture(cb))
+ cb.value.onDemoModeFinished()
+ verify(clock).onDemoModeFinished()
}
@Test
@@ -226,23 +349,21 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
verify(batteryMeterViewController).init()
verify(batteryMeterViewController).ignoreTunerUpdates()
- val inOrder = inOrder(qsCarrierGroupControllerBuilder)
+ val inOrder = Mockito.inOrder(qsCarrierGroupControllerBuilder)
inOrder.verify(qsCarrierGroupControllerBuilder).setQSCarrierGroup(carrierGroup)
inOrder.verify(qsCarrierGroupControllerBuilder).build()
}
@Test
fun `battery mode controller called when qsExpandedFraction changes`() {
- whenever(qsBatteryModeController.getBatteryMode(same(null), eq(0f)))
- .thenReturn(BatteryMeterView.MODE_ON)
- whenever(qsBatteryModeController.getBatteryMode(same(null), eq(1f)))
- .thenReturn(BatteryMeterView.MODE_ESTIMATE)
- controller.qsVisible = true
+ whenever(qsBatteryModeController.getBatteryMode(Mockito.same(null), eq(0f)))
+ .thenReturn(BatteryMeterView.MODE_ON)
+ whenever(qsBatteryModeController.getBatteryMode(Mockito.same(null), eq(1f)))
+ .thenReturn(BatteryMeterView.MODE_ESTIMATE)
+ shadeHeaderController.qsVisible = true
val times = 10
- repeat(times) {
- controller.qsExpandedFraction = it / (times - 1).toFloat()
- }
+ repeat(times) { shadeHeaderController.qsExpandedFraction = it / (times - 1).toFloat() }
verify(batteryMeterView).setPercentShowMode(BatteryMeterView.MODE_ON)
verify(batteryMeterView).setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
@@ -277,89 +398,89 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
@Test
fun testShadeExpanded_true() {
// When shade is expanded, view should be visible regardless of largeScreenActive
- controller.largeScreenActive = false
- controller.qsVisible = true
+ shadeHeaderController.largeScreenActive = false
+ shadeHeaderController.qsVisible = true
assertThat(viewVisibility).isEqualTo(View.VISIBLE)
- controller.largeScreenActive = true
+ shadeHeaderController.largeScreenActive = true
assertThat(viewVisibility).isEqualTo(View.VISIBLE)
}
@Test
fun testShadeExpanded_false() {
// When shade is not expanded, view should be invisible regardless of largeScreenActive
- controller.largeScreenActive = false
- controller.qsVisible = false
+ shadeHeaderController.largeScreenActive = false
+ shadeHeaderController.qsVisible = false
assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
- controller.largeScreenActive = true
+ shadeHeaderController.largeScreenActive = true
assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
}
@Test
fun testLargeScreenActive_false() {
- controller.largeScreenActive = true // Make sure there's a change
- clearInvocations(view)
+ shadeHeaderController.largeScreenActive = true // Make sure there's a change
+ Mockito.clearInvocations(view)
- controller.largeScreenActive = false
+ shadeHeaderController.largeScreenActive = false
- verify(view).setTransition(HEADER_TRANSITION_ID)
+ verify(view).setTransition(ShadeHeaderController.HEADER_TRANSITION_ID)
}
@Test
fun testShadeExpandedFraction() {
// View needs to be visible for this to actually take effect
- controller.qsVisible = true
+ shadeHeaderController.qsVisible = true
- clearInvocations(view)
- controller.shadeExpandedFraction = 0.3f
+ Mockito.clearInvocations(view)
+ shadeHeaderController.shadeExpandedFraction = 0.3f
verify(view).alpha = ShadeInterpolation.getContentAlpha(0.3f)
- clearInvocations(view)
- controller.shadeExpandedFraction = 1f
+ Mockito.clearInvocations(view)
+ shadeHeaderController.shadeExpandedFraction = 1f
verify(view).alpha = ShadeInterpolation.getContentAlpha(1f)
- clearInvocations(view)
- controller.shadeExpandedFraction = 0f
+ Mockito.clearInvocations(view)
+ shadeHeaderController.shadeExpandedFraction = 0f
verify(view).alpha = ShadeInterpolation.getContentAlpha(0f)
}
@Test
fun testQsExpandedFraction_headerTransition() {
- controller.qsVisible = true
- controller.largeScreenActive = false
+ shadeHeaderController.qsVisible = true
+ shadeHeaderController.largeScreenActive = false
- clearInvocations(view)
- controller.qsExpandedFraction = 0.3f
+ Mockito.clearInvocations(view)
+ shadeHeaderController.qsExpandedFraction = 0.3f
verify(view).progress = 0.3f
}
@Test
fun testQsExpandedFraction_largeScreen() {
- controller.qsVisible = true
- controller.largeScreenActive = true
+ shadeHeaderController.qsVisible = true
+ shadeHeaderController.largeScreenActive = true
- clearInvocations(view)
- controller.qsExpandedFraction = 0.3f
- verify(view, never()).progress = anyFloat()
+ Mockito.clearInvocations(view)
+ shadeHeaderController.qsExpandedFraction = 0.3f
+ verify(view, Mockito.never()).progress = anyFloat()
}
@Test
fun testScrollY_headerTransition() {
- controller.largeScreenActive = false
+ shadeHeaderController.largeScreenActive = false
- clearInvocations(view)
- controller.qsScrollY = 20
+ Mockito.clearInvocations(view)
+ shadeHeaderController.qsScrollY = 20
verify(view).scrollY = 20
}
@Test
fun testScrollY_largeScreen() {
- controller.largeScreenActive = true
+ shadeHeaderController.largeScreenActive = true
- clearInvocations(view)
- controller.qsScrollY = 20
- verify(view, never()).scrollY = anyInt()
+ Mockito.clearInvocations(view)
+ shadeHeaderController.qsScrollY = 20
+ verify(view, Mockito.never()).scrollY = anyInt()
}
@Test
@@ -381,9 +502,9 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
verify(chipVisibleChanges.qsConstraintsChanges)!!.invoke(qsConstraints)
verify(chipVisibleChanges.largeScreenConstraintsChanges)!!.invoke(largeScreenConstraints)
- verify(chipNotVisibleChanges.qqsConstraintsChanges, never())!!.invoke(any())
- verify(chipNotVisibleChanges.qsConstraintsChanges, never())!!.invoke(any())
- verify(chipNotVisibleChanges.largeScreenConstraintsChanges, never())!!.invoke(any())
+ verify(chipNotVisibleChanges.qqsConstraintsChanges, Mockito.never())!!.invoke(any())
+ verify(chipNotVisibleChanges.qsConstraintsChanges, Mockito.never())!!.invoke(any())
+ verify(chipNotVisibleChanges.largeScreenConstraintsChanges, Mockito.never())!!.invoke(any())
}
@Test
@@ -401,10 +522,11 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
captor.value.onChipVisibilityRefreshed(false)
- verify(chipVisibleChanges.qqsConstraintsChanges, never())!!.invoke(qqsConstraints)
- verify(chipVisibleChanges.qsConstraintsChanges, never())!!.invoke(qsConstraints)
- verify(chipVisibleChanges.largeScreenConstraintsChanges, never())!!
- .invoke(largeScreenConstraints)
+ verify(chipVisibleChanges.qqsConstraintsChanges, Mockito.never())!!.invoke(qqsConstraints)
+ verify(chipVisibleChanges.qsConstraintsChanges, Mockito.never())!!.invoke(qsConstraints)
+ verify(chipVisibleChanges.largeScreenConstraintsChanges, Mockito.never())!!.invoke(
+ largeScreenConstraints
+ )
verify(chipNotVisibleChanges.qqsConstraintsChanges)!!.invoke(any())
verify(chipNotVisibleChanges.qsConstraintsChanges)!!.invoke(any())
@@ -425,9 +547,15 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
mockInsetsProvider(insetLeft to insetRight, false)
- whenever(combinedShadeHeadersConstraintManager
- .edgesGuidelinesConstraints(anyInt(), anyInt(), anyInt(), anyInt())
- ).thenReturn(mockConstraintsChanges)
+ whenever(
+ combinedShadeHeadersConstraintManager.edgesGuidelinesConstraints(
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt()
+ )
+ )
+ .thenReturn(mockConstraintsChanges)
captor.value.onApplyWindowInsets(view, createWindowInsets())
@@ -453,9 +581,15 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
mockInsetsProvider(insetLeft to insetRight, false)
- whenever(combinedShadeHeadersConstraintManager
- .edgesGuidelinesConstraints(anyInt(), anyInt(), anyInt(), anyInt())
- ).thenReturn(mockConstraintsChanges)
+ whenever(
+ combinedShadeHeadersConstraintManager.edgesGuidelinesConstraints(
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt()
+ )
+ )
+ .thenReturn(mockConstraintsChanges)
captor.value.onApplyWindowInsets(view, createWindowInsets())
@@ -479,8 +613,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
captor.value.onApplyWindowInsets(view, createWindowInsets(null))
verify(combinedShadeHeadersConstraintManager).emptyCutoutConstraints()
- verify(combinedShadeHeadersConstraintManager, never())
- .centerCutoutConstraints(anyBoolean(), anyInt())
+ verify(combinedShadeHeadersConstraintManager, Mockito.never())
+ .centerCutoutConstraints(Mockito.anyBoolean(), anyInt())
verify(mockConstraintsChanges.qqsConstraintsChanges)!!.invoke(any())
verify(mockConstraintsChanges.qsConstraintsChanges)!!.invoke(any())
@@ -499,8 +633,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
captor.value.onApplyWindowInsets(view, createWindowInsets())
verify(combinedShadeHeadersConstraintManager).emptyCutoutConstraints()
- verify(combinedShadeHeadersConstraintManager, never())
- .centerCutoutConstraints(anyBoolean(), anyInt())
+ verify(combinedShadeHeadersConstraintManager, Mockito.never())
+ .centerCutoutConstraints(Mockito.anyBoolean(), anyInt())
verify(mockConstraintsChanges.qqsConstraintsChanges)!!.invoke(any())
verify(mockConstraintsChanges.qsConstraintsChanges)!!.invoke(any())
@@ -521,8 +655,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
captor.value.onApplyWindowInsets(view, createWindowInsets())
verify(combinedShadeHeadersConstraintManager).emptyCutoutConstraints()
- verify(combinedShadeHeadersConstraintManager, never())
- .centerCutoutConstraints(anyBoolean(), anyInt())
+ verify(combinedShadeHeadersConstraintManager, Mockito.never())
+ .centerCutoutConstraints(Mockito.anyBoolean(), anyInt())
verify(mockConstraintsChanges.qqsConstraintsChanges)!!.invoke(any())
verify(mockConstraintsChanges.qsConstraintsChanges)!!.invoke(any())
@@ -543,8 +677,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
captor.value.onApplyWindowInsets(view, createWindowInsets(Rect(1, 2, 3, 4)))
verify(combinedShadeHeadersConstraintManager).emptyCutoutConstraints()
- verify(combinedShadeHeadersConstraintManager, never())
- .centerCutoutConstraints(anyBoolean(), anyInt())
+ verify(combinedShadeHeadersConstraintManager, Mockito.never())
+ .centerCutoutConstraints(Mockito.anyBoolean(), anyInt())
verify(mockConstraintsChanges.qqsConstraintsChanges)!!.invoke(any())
verify(mockConstraintsChanges.qsConstraintsChanges)!!.invoke(any())
@@ -569,13 +703,17 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
mockInsetsProvider(0 to 0, false)
- whenever(combinedShadeHeadersConstraintManager
- .centerCutoutConstraints(anyBoolean(), anyInt())
- ).thenReturn(mockConstraintsChanges)
+ whenever(
+ combinedShadeHeadersConstraintManager.centerCutoutConstraints(
+ Mockito.anyBoolean(),
+ anyInt()
+ )
+ )
+ .thenReturn(mockConstraintsChanges)
captor.value.onApplyWindowInsets(view, createWindowInsets(Rect(0, 0, cutoutWidth, 1)))
- verify(combinedShadeHeadersConstraintManager, never()).emptyCutoutConstraints()
+ verify(combinedShadeHeadersConstraintManager, Mockito.never()).emptyCutoutConstraints()
val offset = (width - paddingLeft - paddingRight - cutoutWidth) / 2
verify(combinedShadeHeadersConstraintManager).centerCutoutConstraints(false, offset)
@@ -602,13 +740,17 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
mockInsetsProvider(0 to 0, false)
- whenever(combinedShadeHeadersConstraintManager
- .centerCutoutConstraints(anyBoolean(), anyInt())
- ).thenReturn(mockConstraintsChanges)
+ whenever(
+ combinedShadeHeadersConstraintManager.centerCutoutConstraints(
+ Mockito.anyBoolean(),
+ anyInt()
+ )
+ )
+ .thenReturn(mockConstraintsChanges)
captor.value.onApplyWindowInsets(view, createWindowInsets(Rect(0, 0, cutoutWidth, 1)))
- verify(combinedShadeHeadersConstraintManager, never()).emptyCutoutConstraints()
+ verify(combinedShadeHeadersConstraintManager, Mockito.never()).emptyCutoutConstraints()
val offset = (width - paddingLeft - paddingRight - cutoutWidth) / 2
verify(combinedShadeHeadersConstraintManager).centerCutoutConstraints(true, offset)
@@ -619,52 +761,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
@Test
fun alarmIconNotIgnored() {
- verify(statusIcons, never()).addIgnoredSlot(
- context.getString(com.android.internal.R.string.status_bar_alarm_clock)
- )
- }
-
- @Test
- fun demoMode_attachDemoMode() {
- verify(demoModeController).addCallback(capture(demoModeControllerCapture))
- demoModeControllerCapture.value.onDemoModeStarted()
- verify(clock).onDemoModeStarted()
- }
-
- @Test
- fun demoMode_detachDemoMode() {
- controller.simulateViewDetached()
- verify(demoModeController).removeCallback(capture(demoModeControllerCapture))
- demoModeControllerCapture.value.onDemoModeFinished()
- verify(clock).onDemoModeFinished()
- }
-
- @Test
- fun animateOutOnStartCustomizing() {
- val animator = Mockito.mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- val duration = 1000L
- whenever(view.animate()).thenReturn(animator)
-
- controller.startCustomizingAnimation(show = true, duration)
-
- verify(animator).setDuration(duration)
- verify(animator).alpha(0f)
- verify(animator).setInterpolator(Interpolators.ALPHA_OUT)
- verify(animator).start()
- }
-
- @Test
- fun animateInOnEndCustomizing() {
- val animator = Mockito.mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- val duration = 1000L
- whenever(view.animate()).thenReturn(animator)
-
- controller.startCustomizingAnimation(show = false, duration)
-
- verify(animator).setDuration(duration)
- verify(animator).alpha(1f)
- verify(animator).setInterpolator(Interpolators.ALPHA_IN)
- verify(animator).start()
+ verify(statusIcons, Mockito.never())
+ .addIgnoredSlot(context.getString(com.android.internal.R.string.status_bar_alarm_clock))
}
@Test
@@ -674,11 +772,11 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
@Test
fun privacyChipParentVisibleAlways() {
- controller.largeScreenActive = true
- controller.largeScreenActive = false
- controller.largeScreenActive = true
+ shadeHeaderController.largeScreenActive = true
+ shadeHeaderController.largeScreenActive = false
+ shadeHeaderController.largeScreenActive = true
- verify(privacyIconsController, never()).onParentInvisible()
+ verify(privacyIconsController, Mockito.never()).onParentInvisible()
}
@Test
@@ -700,9 +798,9 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
fun onDensityOrFontScaleChanged_reloadConstraints() {
// After density or font scale change, constraints need to be reloaded to reflect new
// dimensions.
- reset(qqsConstraints)
- reset(qsConstraints)
- reset(largeScreenConstraints)
+ Mockito.reset(qqsConstraints)
+ Mockito.reset(qsConstraints)
+ Mockito.reset(largeScreenConstraints)
configurationController.notifyDensityOrFontScaleChanged()
@@ -729,11 +827,11 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
}
private fun View.executeLayoutChange(
- left: Int,
- top: Int,
- right: Int,
- bottom: Int,
- listener: View.OnLayoutChangeListener
+ left: Int,
+ top: Int,
+ right: Int,
+ bottom: Int,
+ listener: View.OnLayoutChangeListener
) {
val oldLeft = this.left
val oldTop = this.top
@@ -746,21 +844,19 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
whenever(this.height).thenReturn(bottom - top)
whenever(this.width).thenReturn(right - left)
listener.onLayoutChange(
- this,
- oldLeft,
- oldTop,
- oldRight,
- oldBottom,
- left,
- top,
- right,
- bottom
+ this,
+ oldLeft,
+ oldTop,
+ oldRight,
+ oldBottom,
+ left,
+ top,
+ right,
+ bottom
)
}
- private fun createWindowInsets(
- topCutout: Rect? = Rect()
- ): WindowInsets {
+ private fun createWindowInsets(topCutout: Rect? = Rect()): WindowInsets {
val windowInsets: WindowInsets = mock()
val displayCutout: DisplayCutout = mock()
whenever(windowInsets.displayCutout)
@@ -795,17 +891,30 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
}
private fun setUpDefaultInsets() {
- whenever(combinedShadeHeadersConstraintManager
- .edgesGuidelinesConstraints(anyInt(), anyInt(), anyInt(), anyInt())
- ).thenReturn(EMPTY_CHANGES)
+ whenever(
+ combinedShadeHeadersConstraintManager.edgesGuidelinesConstraints(
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt()
+ )
+ )
+ .thenReturn(EMPTY_CHANGES)
whenever(combinedShadeHeadersConstraintManager.emptyCutoutConstraints())
.thenReturn(EMPTY_CHANGES)
- whenever(combinedShadeHeadersConstraintManager
- .centerCutoutConstraints(anyBoolean(), anyInt())
- ).thenReturn(EMPTY_CHANGES)
- whenever(combinedShadeHeadersConstraintManager
- .privacyChipVisibilityConstraints(anyBoolean())
- ).thenReturn(EMPTY_CHANGES)
+ whenever(
+ combinedShadeHeadersConstraintManager.centerCutoutConstraints(
+ Mockito.anyBoolean(),
+ anyInt()
+ )
+ )
+ .thenReturn(EMPTY_CHANGES)
+ whenever(
+ combinedShadeHeadersConstraintManager.privacyChipVisibilityConstraints(
+ Mockito.anyBoolean()
+ )
+ )
+ .thenReturn(EMPTY_CHANGES)
whenever(insetsProvider.getStatusBarContentInsetsForCurrentRotation())
.thenReturn(Pair(0, 0).toAndroidPair())
whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(false)
@@ -814,11 +923,11 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
private fun setupCurrentInsets(cutout: DisplayCutout?) {
val mockedDisplay =
- mock<Display>().also { display -> whenever(display.cutout).thenReturn(cutout) }
+ mock<Display>().also { display -> whenever(display.cutout).thenReturn(cutout) }
whenever(viewContext.display).thenReturn(mockedDisplay)
}
- private fun<T, U> Pair<T, U>.toAndroidPair(): android.util.Pair<T, U> {
+ private fun <T, U> Pair<T, U>.toAndroidPair(): android.util.Pair<T, U> {
return android.util.Pair(first, second)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImplTest.kt
new file mode 100644
index 000000000000..8309342d2c60
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImplTest.kt
@@ -0,0 +1,144 @@
+package com.android.systemui.shade.transition
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.policy.FakeConfigurationController
+import com.google.common.truth.Expect
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class LargeScreenShadeInterpolatorImplTest : SysuiTestCase() {
+ @get:Rule val expect: Expect = Expect.create()
+
+ private val portraitShadeInterpolator = LargeScreenPortraitShadeInterpolator()
+ private val splitShadeInterpolator = SplitShadeInterpolator()
+ private val configurationController = FakeConfigurationController()
+ private val impl =
+ LargeScreenShadeInterpolatorImpl(
+ configurationController,
+ context,
+ splitShadeInterpolator,
+ portraitShadeInterpolator
+ )
+
+ @Test
+ fun getBehindScrimAlpha_inSplitShade_usesSplitShadeValue() {
+ setSplitShadeEnabled(true)
+
+ assertInterpolation(
+ actual = { fraction -> impl.getBehindScrimAlpha(fraction) },
+ expected = { fraction -> splitShadeInterpolator.getBehindScrimAlpha(fraction) }
+ )
+ }
+
+ @Test
+ fun getBehindScrimAlpha_inPortraitShade_usesPortraitShadeValue() {
+ setSplitShadeEnabled(false)
+
+ assertInterpolation(
+ actual = { fraction -> impl.getBehindScrimAlpha(fraction) },
+ expected = { fraction -> portraitShadeInterpolator.getBehindScrimAlpha(fraction) }
+ )
+ }
+
+ @Test
+ fun getNotificationScrimAlpha_inSplitShade_usesSplitShadeValue() {
+ setSplitShadeEnabled(true)
+
+ assertInterpolation(
+ actual = { fraction -> impl.getNotificationScrimAlpha(fraction) },
+ expected = { fraction -> splitShadeInterpolator.getNotificationScrimAlpha(fraction) }
+ )
+ }
+ @Test
+ fun getNotificationScrimAlpha_inPortraitShade_usesPortraitShadeValue() {
+ setSplitShadeEnabled(false)
+
+ assertInterpolation(
+ actual = { fraction -> impl.getNotificationScrimAlpha(fraction) },
+ expected = { fraction -> portraitShadeInterpolator.getNotificationScrimAlpha(fraction) }
+ )
+ }
+
+ @Test
+ fun getNotificationContentAlpha_inSplitShade_usesSplitShadeValue() {
+ setSplitShadeEnabled(true)
+
+ assertInterpolation(
+ actual = { fraction -> impl.getNotificationContentAlpha(fraction) },
+ expected = { fraction -> splitShadeInterpolator.getNotificationContentAlpha(fraction) }
+ )
+ }
+
+ @Test
+ fun getNotificationContentAlpha_inPortraitShade_usesPortraitShadeValue() {
+ setSplitShadeEnabled(false)
+
+ assertInterpolation(
+ actual = { fraction -> impl.getNotificationContentAlpha(fraction) },
+ expected = { fraction ->
+ portraitShadeInterpolator.getNotificationContentAlpha(fraction)
+ }
+ )
+ }
+
+ @Test
+ fun getNotificationFooterAlpha_inSplitShade_usesSplitShadeValue() {
+ setSplitShadeEnabled(true)
+
+ assertInterpolation(
+ actual = { fraction -> impl.getNotificationFooterAlpha(fraction) },
+ expected = { fraction -> splitShadeInterpolator.getNotificationFooterAlpha(fraction) }
+ )
+ }
+ @Test
+ fun getNotificationFooterAlpha_inPortraitShade_usesPortraitShadeValue() {
+ setSplitShadeEnabled(false)
+
+ assertInterpolation(
+ actual = { fraction -> impl.getNotificationFooterAlpha(fraction) },
+ expected = { fraction ->
+ portraitShadeInterpolator.getNotificationFooterAlpha(fraction)
+ }
+ )
+ }
+
+ @Test
+ fun getQsAlpha_inSplitShade_usesSplitShadeValue() {
+ setSplitShadeEnabled(true)
+
+ assertInterpolation(
+ actual = { fraction -> impl.getQsAlpha(fraction) },
+ expected = { fraction -> splitShadeInterpolator.getQsAlpha(fraction) }
+ )
+ }
+ @Test
+ fun getQsAlpha_inPortraitShade_usesPortraitShadeValue() {
+ setSplitShadeEnabled(false)
+
+ assertInterpolation(
+ actual = { fraction -> impl.getQsAlpha(fraction) },
+ expected = { fraction -> portraitShadeInterpolator.getQsAlpha(fraction) }
+ )
+ }
+
+ private fun setSplitShadeEnabled(enabled: Boolean) {
+ overrideResource(R.bool.config_use_split_notification_shade, enabled)
+ configurationController.notifyConfigurationChanged()
+ }
+
+ private fun assertInterpolation(
+ actual: (fraction: Float) -> Float,
+ expected: (fraction: Float) -> Float
+ ) {
+ for (i in 0..10) {
+ val fraction = i / 10f
+ expect.that(actual(fraction)).isEqualTo(expected(fraction))
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LinearLargeScreenShadeInterpolator.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LinearLargeScreenShadeInterpolator.kt
new file mode 100644
index 000000000000..d24bcdc834a7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LinearLargeScreenShadeInterpolator.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.transition
+
+class LinearLargeScreenShadeInterpolator : LargeScreenShadeInterpolator {
+ override fun getBehindScrimAlpha(fraction: Float) = fraction
+ override fun getNotificationScrimAlpha(fraction: Float) = fraction
+ override fun getNotificationContentAlpha(fraction: Float) = fraction
+ override fun getNotificationFooterAlpha(fraction: Float) = fraction
+ override fun getQsAlpha(fraction: Float) = fraction
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
index 84f86561d073..cbf54854759b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
@@ -5,6 +5,8 @@ import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.shade.STATE_CLOSED
import com.android.systemui.shade.STATE_OPEN
import com.android.systemui.shade.STATE_OPENING
@@ -30,6 +32,7 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() {
@Mock private lateinit var dumpManager: DumpManager
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
@Mock private lateinit var headsUpManager: HeadsUpManager
+ @Mock private lateinit var featureFlags: FeatureFlags
private val configurationController = FakeConfigurationController()
private lateinit var controller: ScrimShadeTransitionController
@@ -45,7 +48,8 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() {
scrimController,
context.resources,
statusBarStateController,
- headsUpManager)
+ headsUpManager,
+ featureFlags)
controller.onPanelStateChanged(STATE_OPENING)
}
@@ -107,6 +111,19 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() {
}
@Test
+ fun onPanelExpansionChanged_inSplitShade_flagTrue_setsFractionEqualToEventFraction() {
+ whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+ .thenReturn(true)
+ whenever(statusBarStateController.currentOrUpcomingState)
+ .thenReturn(StatusBarState.SHADE)
+ setSplitShadeEnabled(true)
+
+ controller.onPanelExpansionChanged(EXPANSION_EVENT)
+
+ verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction)
+ }
+
+ @Test
fun onPanelExpansionChanged_inSplitShade_onKeyguard_setsFractionEqualToEventFraction() {
whenever(statusBarStateController.currentOrUpcomingState)
.thenReturn(StatusBarState.KEYGUARD)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
index 7cac854c0853..d5a1f804e6a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
@@ -2,37 +2,24 @@ package com.android.systemui.shade.transition
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
-import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.NotificationPanelViewController
import com.android.systemui.shade.STATE_OPENING
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionStateManager
-import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.policy.FakeConfigurationController
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@SmallTest
class ShadeTransitionControllerTest : SysuiTestCase() {
- @Mock private lateinit var npvc: NotificationPanelViewController
- @Mock private lateinit var nsslController: NotificationStackScrollLayoutController
- @Mock private lateinit var qs: QS
- @Mock private lateinit var noOpOverScroller: NoOpOverScroller
- @Mock private lateinit var splitShadeOverScroller: SplitShadeOverScroller
@Mock private lateinit var scrimShadeTransitionController: ScrimShadeTransitionController
@Mock private lateinit var dumpManager: DumpManager
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
@@ -52,119 +39,19 @@ class ShadeTransitionControllerTest : SysuiTestCase() {
shadeExpansionStateManager,
dumpManager,
context,
- splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller },
- noOpOverScroller,
scrimShadeTransitionController,
statusBarStateController,
)
-
- // Resetting as they are notified upon initialization.
- reset(noOpOverScroller, splitShadeOverScroller)
- }
-
- @Test
- fun onPanelExpansionChanged_inSplitShade_forwardsToSplitShadeOverScroller() {
- initLateProperties()
- enableSplitShade()
-
- startPanelExpansion()
-
- verify(splitShadeOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(splitShadeOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(noOpOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_propertiesNotInitialized_forwardsToNoOpOverScroller() {
- enableSplitShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_onKeyguard_forwardsToNoOpOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnKeyguard()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_onLockedShade_forwardsToNoOpOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnLockedShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelExpansionChanged_inSplitShade_onUnlockedShade_forwardsToSplitShadeOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnUnlockedShade()
-
- startPanelExpansion()
-
- verify(splitShadeOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(splitShadeOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(noOpOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_notInSplitShade_forwardsToNoOpOverScroller() {
- initLateProperties()
- disableSplitShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
}
@Test
fun onPanelStateChanged_forwardsToScrimTransitionController() {
- initLateProperties()
-
startPanelExpansion()
verify(scrimShadeTransitionController).onPanelStateChanged(STATE_OPENING)
verify(scrimShadeTransitionController).onPanelExpansionChanged(DEFAULT_EXPANSION_EVENT)
}
- private fun initLateProperties() {
- controller.qs = qs
- controller.notificationStackScrollLayoutController = nsslController
- controller.notificationPanelViewController = npvc
- }
-
- private fun disableSplitShade() {
- setSplitShadeEnabled(false)
- }
-
- private fun enableSplitShade() {
- setSplitShadeEnabled(true)
- }
-
- private fun setSplitShadeEnabled(enabled: Boolean) {
- overrideResource(R.bool.config_use_split_notification_shade, enabled)
- configurationController.notifyConfigurationChanged()
- }
-
private fun startPanelExpansion() {
shadeExpansionStateManager.onPanelExpansionChanged(
DEFAULT_EXPANSION_EVENT.fraction,
@@ -174,23 +61,6 @@ class ShadeTransitionControllerTest : SysuiTestCase() {
)
}
- private fun setOnKeyguard() {
- setShadeState(StatusBarState.KEYGUARD)
- }
-
- private fun setOnLockedShade() {
- setShadeState(StatusBarState.SHADE_LOCKED)
- }
-
- private fun setOnUnlockedShade() {
- setShadeState(StatusBarState.SHADE)
- }
-
- private fun setShadeState(state: Int) {
- whenever(statusBarStateController.state).thenReturn(state)
- whenever(statusBarStateController.currentOrUpcomingState).thenReturn(state)
- }
-
companion object {
private const val DEFAULT_DRAG_DOWN_AMOUNT = 123f
private val DEFAULT_EXPANSION_EVENT =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
deleted file mode 100644
index 0e48b4835dfe..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package com.android.systemui.shade.transition
-
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.STATE_CLOSED
-import com.android.systemui.shade.STATE_OPEN
-import com.android.systemui.shade.STATE_OPENING
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.policy.FakeConfigurationController
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.atLeastOnce
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@SmallTest
-class SplitShadeOverScrollerTest : SysuiTestCase() {
-
- @Mock private lateinit var dumpManager: DumpManager
- @Mock private lateinit var scrimController: ScrimController
- @Mock private lateinit var qs: QS
- @Mock private lateinit var nsslController: NotificationStackScrollLayoutController
-
- private val configurationController = FakeConfigurationController()
- private lateinit var overScroller: SplitShadeOverScroller
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
-
- whenever(nsslController.height).thenReturn(1000)
- overScroller =
- SplitShadeOverScroller(
- configurationController,
- dumpManager,
- context,
- scrimController,
- { qs },
- { nsslController })
- }
-
- @Test
- fun onDragDownAmountChanged_panelOpening_overScrolls_basedOnHeightAndMaxAmount() {
- val maxOverScrollAmount = 50
- val dragDownAmount = 100f
- overrideResource(R.dimen.shade_max_over_scroll_amount, maxOverScrollAmount)
- configurationController.notifyConfigurationChanged()
-
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(dragDownAmount)
-
- val expectedOverScrollAmount =
- (dragDownAmount / nsslController.height * maxOverScrollAmount).toInt()
- verify(qs).setOverScrollAmount(expectedOverScrollAmount)
- verify(nsslController).setOverScrollAmount(expectedOverScrollAmount)
- verify(scrimController).setNotificationsOverScrollAmount(expectedOverScrollAmount)
- }
-
- @Test
- fun onDragDownAmountChanged_panelClosed_doesNotOverScroll() {
- overScroller.onPanelStateChanged(STATE_CLOSED)
- overScroller.onDragDownAmountChanged(100f)
-
- verifyZeroInteractions(qs, scrimController, nsslController)
- }
-
- @Test
- fun onDragDownAmountChanged_panelOpen_doesNotOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPEN)
- overScroller.onDragDownAmountChanged(100f)
-
- verifyZeroInteractions(qs, scrimController, nsslController)
- }
-
- @Test
- fun onPanelStateChanged_opening_thenOpen_releasesOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(100f)
-
- overScroller.onPanelStateChanged(STATE_OPEN)
- overScroller.finishAnimations()
-
- verify(qs, atLeastOnce()).setOverScrollAmount(0)
- verify(scrimController, atLeastOnce()).setNotificationsOverScrollAmount(0)
- verify(nsslController, atLeastOnce()).setOverScrollAmount(0)
- }
-
- @Test
- fun onPanelStateChanged_opening_thenClosed_releasesOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(100f)
-
- overScroller.onPanelStateChanged(STATE_CLOSED)
- overScroller.finishAnimations()
-
- verify(qs, atLeastOnce()).setOverScrollAmount(0)
- verify(scrimController, atLeastOnce()).setNotificationsOverScrollAmount(0)
- verify(nsslController, atLeastOnce()).setOverScrollAmount(0)
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
index 7a74b1229c5c..56fc0c74dafa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
@@ -36,21 +36,26 @@ class UnfoldConstantTranslateAnimatorTest : SysuiTestCase() {
private val progressProvider = TestUnfoldTransitionProvider()
- @Mock private lateinit var parent: ViewGroup
+ @Mock
+ private lateinit var parent: ViewGroup
+
+ @Mock
+ private lateinit var shouldBeAnimated: () -> Boolean
private lateinit var animator: UnfoldConstantTranslateAnimator
- private val viewsIdToRegister =
- setOf(
- ViewIdToTranslate(START_VIEW_ID, Direction.START),
- ViewIdToTranslate(END_VIEW_ID, Direction.END))
+ private val viewsIdToRegister
+ get() =
+ setOf(
+ ViewIdToTranslate(START_VIEW_ID, Direction.START, shouldBeAnimated),
+ ViewIdToTranslate(END_VIEW_ID, Direction.END, shouldBeAnimated)
+ )
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
-
- animator =
- UnfoldConstantTranslateAnimator(viewsIdToRegister, progressProvider)
+ whenever(shouldBeAnimated.invoke()).thenReturn(true)
+ animator = UnfoldConstantTranslateAnimator(viewsIdToRegister, progressProvider)
animator.init(parent, MAX_TRANSLATION)
}
@@ -96,6 +101,20 @@ class UnfoldConstantTranslateAnimatorTest : SysuiTestCase() {
moveAndValidate(listOf(leftView to START, rightView to END), View.LAYOUT_DIRECTION_LTR)
}
+ @Test
+ fun onTransition_completeStartedTranslation() {
+ // GIVEN
+ val leftView = View(context)
+ whenever(parent.findViewById<View>(START_VIEW_ID)).thenReturn(leftView)
+ // To start animation, shouldBeAnimated should return true.
+ // There is a possibility for shouldBeAnimated to return false during the animation.
+ whenever(shouldBeAnimated.invoke()).thenReturn(true).thenReturn(false)
+
+ // shouldBeAnimated state may change during the animation.
+ // However, started animation should be completed.
+ moveAndValidate(listOf(leftView to START), View.LAYOUT_DIRECTION_LTR)
+ }
+
private fun moveAndValidate(list: List<Pair<View, Int>>, layoutDirection: Int) {
// Compare values as ints because -0f != 0f
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt
index cc45cf88fa18..2eca78a0412b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt
@@ -57,7 +57,18 @@ class AnimatableClockViewTest : SysuiTestCase() {
clockView.measure(50, 50)
verify(mockTextAnimator).glyphFilter = any()
- verify(mockTextAnimator).setTextStyle(300, -1.0f, 200, false, 350L, null, 0L, null)
+ verify(mockTextAnimator)
+ .setTextStyle(
+ weight = 300,
+ textSize = -1.0f,
+ color = 200,
+ strokeWidth = -1F,
+ animate = false,
+ duration = 350L,
+ interpolator = null,
+ delay = 0L,
+ onAnimationEnd = null
+ )
verifyNoMoreInteractions(mockTextAnimator)
}
@@ -68,8 +79,30 @@ class AnimatableClockViewTest : SysuiTestCase() {
clockView.animateAppearOnLockscreen()
verify(mockTextAnimator, times(2)).glyphFilter = any()
- verify(mockTextAnimator).setTextStyle(100, -1.0f, 200, false, 0L, null, 0L, null)
- verify(mockTextAnimator).setTextStyle(300, -1.0f, 200, true, 350L, null, 0L, null)
+ verify(mockTextAnimator)
+ .setTextStyle(
+ weight = 100,
+ textSize = -1.0f,
+ color = 200,
+ strokeWidth = -1F,
+ animate = false,
+ duration = 0L,
+ interpolator = null,
+ delay = 0L,
+ onAnimationEnd = null
+ )
+ verify(mockTextAnimator)
+ .setTextStyle(
+ weight = 300,
+ textSize = -1.0f,
+ color = 200,
+ strokeWidth = -1F,
+ animate = true,
+ duration = 350L,
+ interpolator = null,
+ delay = 0L,
+ onAnimationEnd = null
+ )
verifyNoMoreInteractions(mockTextAnimator)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index 26eff61066ee..1fdb3647fcb2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -35,7 +35,6 @@ import junit.framework.Assert.fail
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
-import org.json.JSONException
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -271,10 +270,14 @@ class ClockRegistryTest : SysuiTestCase() {
@Test
fun jsonDeserialization_gotExpectedObject() {
- val expected = ClockSettings("ID", null).apply { _applied_timestamp = 500 }
+ val expected = ClockSettings("ID", null).apply {
+ metadata.put("appliedTimestamp", 500)
+ }
val actual = ClockSettings.deserialize("""{
"clockId":"ID",
- "_applied_timestamp":500
+ "metadata": {
+ "appliedTimestamp":500
+ }
}""")
assertEquals(expected, actual)
}
@@ -291,29 +294,32 @@ class ClockRegistryTest : SysuiTestCase() {
val expected = ClockSettings("ID", null)
val actual = ClockSettings.deserialize("""{
"clockId":"ID",
- "_applied_timestamp":null
+ "metadata":null
}""")
assertEquals(expected, actual)
}
- @Test(expected = JSONException::class)
- fun jsonDeserialization_noId_threwException() {
- val expected = ClockSettings(null, null).apply { _applied_timestamp = 500 }
- val actual = ClockSettings.deserialize("{\"_applied_timestamp\":500}")
+ @Test
+ fun jsonDeserialization_noId_deserializedEmpty() {
+ val expected = ClockSettings(null, null).apply {
+ metadata.put("appliedTimestamp", 500)
+ }
+ val actual = ClockSettings.deserialize("{\"metadata\":{\"appliedTimestamp\":500}}")
assertEquals(expected, actual)
}
@Test
fun jsonSerialization_gotExpectedString() {
- val expected = "{\"clockId\":\"ID\",\"_applied_timestamp\":500}"
- val actual = ClockSettings.serialize(ClockSettings("ID", null)
- .apply { _applied_timestamp = 500 })
+ val expected = "{\"clockId\":\"ID\",\"metadata\":{\"appliedTimestamp\":500}}"
+ val actual = ClockSettings.serialize(ClockSettings("ID", null).apply {
+ metadata.put("appliedTimestamp", 500)
+ })
assertEquals(expected, actual)
}
@Test
fun jsonSerialization_noTimestamp_gotExpectedString() {
- val expected = "{\"clockId\":\"ID\"}"
+ val expected = "{\"clockId\":\"ID\",\"metadata\":{}}"
val actual = ClockSettings.serialize(ClockSettings("ID", null))
assertEquals(expected, actual)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index cd2efc061b72..7fa27f34cd9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -26,6 +26,7 @@ import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.ClockSettings
import com.android.systemui.shared.clocks.DefaultClockController.Companion.DOZE_COLOR
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
@@ -40,7 +41,6 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyFloat
-import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.notNull
import org.mockito.Mock
import org.mockito.Mockito.never
@@ -97,13 +97,14 @@ class DefaultClockProviderTest : SysuiTestCase() {
@Test
fun defaultClock_initialize() {
val clock = provider.createClock(DEFAULT_CLOCK_ID)
- verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
- verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
+ verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
clock.initialize(resources, 0f, 0f)
- verify(mockSmallClockView).setColors(eq(DOZE_COLOR), anyInt())
- verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
+ val expectedColor = 0
+ verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
verify(mockSmallClockView).onTimeZoneChanged(notNull())
verify(mockLargeClockView).onTimeZoneChanged(notNull())
verify(mockSmallClockView).refreshTime()
@@ -159,15 +160,31 @@ class DefaultClockProviderTest : SysuiTestCase() {
@Test
fun defaultClock_events_onColorPaletteChanged() {
+ val expectedColor = 0
val clock = provider.createClock(DEFAULT_CLOCK_ID)
- verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
- verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
+ verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
clock.events.onColorPaletteChanged(resources)
- verify(mockSmallClockView).setColors(eq(DOZE_COLOR), anyInt())
- verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
+ verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
+ }
+
+ @Test
+ fun defaultClock_events_onSeedColorChanged() {
+ val initSeedColor = 10
+ val newSeedColor = 20
+ val clock = provider.createClock(ClockSettings(DEFAULT_CLOCK_ID, initSeedColor))
+
+ verify(mockSmallClockView).setColors(DOZE_COLOR, initSeedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, initSeedColor)
+
+ clock.events.onSeedColorChanged(newSeedColor)
+
+ verify(mockSmallClockView).setColors(DOZE_COLOR, newSeedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, newSeedColor)
}
@Test
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 406826b860d4..b7dfea7bf7c5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -1031,24 +1031,6 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
}
@Test
- public void onRefreshBatteryInfo_pluggedWithOverheat_presentChargingLimited() {
- createController();
- BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_DISCHARGING,
- 80 /* level */, BatteryManager.BATTERY_PLUGGED_AC,
- BatteryManager.BATTERY_HEALTH_OVERHEAT, 0 /* maxChargingWattage */,
- true /* present */);
-
- mController.getKeyguardCallback().onRefreshBatteryInfo(status);
- mController.setVisible(true);
-
- verifyIndicationMessage(
- INDICATION_TYPE_BATTERY,
- mContext.getString(
- R.string.keyguard_plugged_in_charging_limited,
- NumberFormat.getPercentInstance().format(80 / 100f)));
- }
-
- @Test
public void onRefreshBatteryInfo_fullChargedWithOverheat_presentChargingLimited() {
createController();
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index d99cdd514f37..ab615f99ebad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -211,16 +211,6 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
}
@Test
- fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() {
- whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
- false)
- transitionController.goToLockedShade(null)
- verify(statusbarStateController, never()).setState(anyInt())
- verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
- verify(mCentralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
- }
-
- @Test
fun testTriggeringBouncerNoNotificationsOnLockscreen() {
whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
transitionController.goToLockedShade(null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 452606dfcca4..8ee1ea8a9916 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -44,6 +44,7 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
+import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -354,7 +355,8 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
mDeviceProvisionedController,
mKeyguardStateController,
mSettings,
- mock(DumpManager.class));
+ mock(DumpManager.class),
+ mock(LockPatternUtils.class));
}
public BroadcastReceiver getBaseBroadcastReceiverForTest() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt
new file mode 100644
index 000000000000..cd0646543e69
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.events
+
+/**
+ * This is a freely configurable implementation of [StatusEvent]. It is intended to be used in
+ * tests.
+ */
+class FakeStatusEvent(
+ override val viewCreator: ViewCreator,
+ override val priority: Int = 50,
+ override var forceVisible: Boolean = false,
+ override val showAnimation: Boolean = true,
+ override var contentDescription: String? = "",
+) : StatusEvent
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
new file mode 100644
index 000000000000..08a9f3139d71
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
@@ -0,0 +1,470 @@
+/*
+ * 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.statusbar.events
+
+import android.graphics.Rect
+import android.os.Process
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.view.View
+import android.widget.FrameLayout
+import androidx.core.animation.AnimatorTestRule
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.privacy.OngoingPrivacyChip
+import com.android.systemui.statusbar.BatteryStatusChip
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import junit.framework.Assert.assertEquals
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+class SystemStatusAnimationSchedulerImplTest : SysuiTestCase() {
+
+ @Mock private lateinit var systemEventCoordinator: SystemEventCoordinator
+ @Mock private lateinit var statusBarWindowController: StatusBarWindowController
+ @Mock private lateinit var statusBarContentInsetProvider: StatusBarContentInsetsProvider
+ @Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var listener: SystemStatusAnimationCallback
+
+ private lateinit var systemClock: FakeSystemClock
+ private lateinit var chipAnimationController: SystemEventChipAnimationController
+ private lateinit var systemStatusAnimationScheduler: SystemStatusAnimationScheduler
+ private val fakeFeatureFlags = FakeFeatureFlags()
+
+ @get:Rule val animatorTestRule = AnimatorTestRule()
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+
+ fakeFeatureFlags.set(Flags.PLUG_IN_STATUS_BAR_CHIP, true)
+
+ systemClock = FakeSystemClock()
+ chipAnimationController =
+ SystemEventChipAnimationController(
+ mContext,
+ statusBarWindowController,
+ statusBarContentInsetProvider,
+ fakeFeatureFlags
+ )
+
+ // ensure that isTooEarly() check in SystemStatusAnimationScheduler does not return true
+ systemClock.advanceTime(Process.getStartUptimeMillis() + MIN_UPTIME)
+
+ // StatusBarContentInsetProvider is mocked. Ensure that it returns some mocked values.
+ whenever(statusBarContentInsetProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(android.util.Pair(10, 10))
+ whenever(statusBarContentInsetProvider.getStatusBarContentAreaForCurrentRotation())
+ .thenReturn(Rect(10, 0, 990, 100))
+
+ // StatusBarWindowController is mocked. The addViewToWindow function needs to be mocked to
+ // ensure that the chip view is added to a parent view
+ whenever(statusBarWindowController.addViewToWindow(any(), any())).then {
+ val statusbarFake = FrameLayout(mContext)
+ statusbarFake.layout(0, 0, 1000, 100)
+ statusbarFake.addView(
+ it.arguments[0] as View,
+ it.arguments[1] as FrameLayout.LayoutParams
+ )
+ }
+ }
+
+ @Test
+ fun testBatteryStatusEvent_standardAnimationLifecycle() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ val batteryChip = createAndScheduleFakeBatteryEvent()
+
+ // assert that animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip debounce delay
+ advanceTimeBy(DEBOUNCE_DELAY + 1)
+ // status chip starts animating in after debounce delay
+ assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(0f, batteryChip.contentView.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ verify(listener, times(1)).onSystemEventAnimationBegin()
+
+ // skip appear animation
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ // assert that status chip is visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, batteryChip.contentView.alpha)
+ assertEquals(1f, batteryChip.view.alpha)
+
+ // skip status chip display time
+ advanceTimeBy(DISPLAY_LENGTH + 1)
+ // assert that it is still visible but switched to the ANIMATING_OUT state
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, batteryChip.contentView.alpha)
+ assertEquals(1f, batteryChip.view.alpha)
+ verify(listener, times(1)).onSystemEventAnimationFinish(false)
+
+ // skip disappear animation
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+ // assert that it is not visible anymore
+ assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(0f, batteryChip.contentView.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ }
+
+ @Test
+ fun testPrivacyStatusEvent_standardAnimationLifecycle() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ val privacyChip = createAndScheduleFakePrivacyEvent()
+
+ // assert that animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip debounce delay
+ advanceTimeBy(DEBOUNCE_DELAY + 1)
+ // status chip starts animating in after debounce delay
+ assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(0f, privacyChip.view.alpha)
+ verify(listener, times(1)).onSystemEventAnimationBegin()
+
+ // skip appear animation
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ advanceTimeBy(APPEAR_ANIMATION_DURATION + 1)
+ // assert that status chip is visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+
+ // skip status chip display time
+ advanceTimeBy(DISPLAY_LENGTH + 1)
+ // assert that it is still visible but switched to the ANIMATING_OUT state
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+ verify(listener, times(1)).onSystemEventAnimationFinish(true)
+ verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
+
+ // skip transition to persistent dot
+ advanceTimeBy(DISAPPEAR_ANIMATION_DURATION + 1)
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+ // assert that it the dot is now visible
+ assertEquals(SHOWING_PERSISTENT_DOT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+
+ // notify SystemStatusAnimationScheduler to remove persistent dot
+ systemStatusAnimationScheduler.removePersistentDot()
+ // assert that IDLE state is entered
+ assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onHidePersistentDot()
+ }
+
+ @Test
+ fun testHighPriorityEvent_takesPrecedenceOverScheduledLowPriorityEvent() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule low priority event
+ val batteryChip = createAndScheduleFakeBatteryEvent()
+ batteryChip.view.alpha = 0f
+
+ // assert that animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // create and schedule high priority event
+ val privacyChip = createAndScheduleFakePrivacyEvent()
+
+ // assert that animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip debounce delay and appear animation duration
+ fastForwardAnimationToState(RUNNING_CHIP_ANIM)
+
+ // high priority status chip is visible while low priority status chip is not visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ }
+
+ @Test
+ fun testHighPriorityEvent_cancelsCurrentlyDisplayedLowPriorityEvent() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule low priority event
+ val batteryChip = createAndScheduleFakeBatteryEvent()
+
+ // fast forward to RUNNING_CHIP_ANIM state
+ fastForwardAnimationToState(RUNNING_CHIP_ANIM)
+
+ // assert that chip is displayed
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, batteryChip.view.alpha)
+
+ // create and schedule high priority event
+ val privacyChip = createAndScheduleFakePrivacyEvent()
+
+ // ensure that the event cancellation coroutine is started by the test scope
+ testScheduler.runCurrent()
+
+ // assert that currently displayed chip is immediately animated out
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip disappear animation
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+
+ // assert that high priority privacy chip animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip debounce delay and appear animation
+ advanceTimeBy(DEBOUNCE_DELAY + APPEAR_ANIMATION_DURATION + 1)
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+
+ // high priority status chip is visible while low priority status chip is not visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ }
+
+ @Test
+ fun testHighPriorityEvent_cancelsCurrentlyAnimatedLowPriorityEvent() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule low priority event
+ val batteryChip = createAndScheduleFakeBatteryEvent()
+
+ // skip debounce delay
+ advanceTimeBy(DEBOUNCE_DELAY + 1)
+
+ // assert that chip is animated in
+ assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+
+ // create and schedule high priority event
+ val privacyChip = createAndScheduleFakePrivacyEvent()
+
+ // ensure that the event cancellation coroutine is started by the test scope
+ testScheduler.runCurrent()
+
+ // assert that currently animated chip keeps animating
+ assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip appear animation
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ advanceTimeBy(APPEAR_ANIMATION_DURATION + 1)
+
+ // assert that low priority chip is animated out immediately after finishing the appear
+ // animation
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip disappear animation
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+
+ // assert that high priority privacy chip animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip debounce delay and appear animation
+ advanceTimeBy(DEBOUNCE_DELAY + APPEAR_ANIMATION_DURATION + 1)
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+
+ // high priority status chip is visible while low priority status chip is not visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ }
+
+ @Test
+ fun testHighPriorityEvent_isNotReplacedByLowPriorityEvent() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule high priority event
+ val privacyChip = createAndScheduleFakePrivacyEvent()
+
+ // create and schedule low priority event
+ val batteryChip = createAndScheduleFakeBatteryEvent()
+ batteryChip.view.alpha = 0f
+
+ // skip debounce delay and appear animation
+ advanceTimeBy(DEBOUNCE_DELAY + APPEAR_ANIMATION_DURATION + 1)
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+
+ // high priority status chip is visible while low priority status chip is not visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ }
+
+ @Test
+ fun testPrivacyDot_isRemoved() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule high priority event
+ createAndScheduleFakePrivacyEvent()
+
+ // skip chip animation lifecycle and fast forward to SHOWING_PERSISTENT_DOT state
+ fastForwardAnimationToState(SHOWING_PERSISTENT_DOT)
+ assertEquals(SHOWING_PERSISTENT_DOT, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
+
+ // remove persistent dot and verify that animationState changes to IDLE
+ systemStatusAnimationScheduler.removePersistentDot()
+ assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onHidePersistentDot()
+ }
+
+ @Test
+ fun testPrivacyDot_isRemovedDuringChipAnimation() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule high priority event
+ createAndScheduleFakePrivacyEvent()
+
+ // skip chip animation lifecycle and fast forward to RUNNING_CHIP_ANIM state
+ fastForwardAnimationToState(RUNNING_CHIP_ANIM)
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+
+ // request removal of persistent dot
+ systemStatusAnimationScheduler.removePersistentDot()
+
+ // skip display time and verify that disappear animation is run
+ advanceTimeBy(DISPLAY_LENGTH + 1)
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip disappear animation and verify that animationState changes to IDLE instead of
+ // SHOWING_PERSISTENT_DOT
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+ assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ // verify that the persistent dot callbacks are not invoked
+ verify(listener, never()).onSystemStatusAnimationTransitionToPersistentDot(any())
+ verify(listener, never()).onHidePersistentDot()
+ }
+
+ @Test
+ fun testNewEvent_isScheduled_whenPostedDuringRemovalAnimation() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule high priority event
+ createAndScheduleFakePrivacyEvent()
+
+ // skip chip animation lifecycle and fast forward to ANIMATING_OUT state
+ fastForwardAnimationToState(ANIMATING_OUT)
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
+
+ // request removal of persistent dot
+ systemStatusAnimationScheduler.removePersistentDot()
+ testScheduler.runCurrent()
+
+ // schedule another high priority event while the event is animating out
+ createAndScheduleFakePrivacyEvent()
+
+ // verify that the state is still ANIMATING_OUT
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip disappear animation duration and verify that new state is ANIMATION_QUEUED
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+ testScheduler.runCurrent()
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ // also verify that onHidePersistentDot callback is called
+ verify(listener, times(1)).onHidePersistentDot()
+ }
+
+ private fun TestScope.fastForwardAnimationToState(@SystemAnimationState animationState: Int) {
+ // this function should only be called directly after posting a status event
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ if (animationState == IDLE || animationState == ANIMATION_QUEUED) return
+ // skip debounce delay
+ advanceTimeBy(DEBOUNCE_DELAY + 1)
+
+ // status chip starts animating in after debounce delay
+ assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onSystemEventAnimationBegin()
+ if (animationState == ANIMATING_IN) return
+
+ // skip appear animation
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ if (animationState == RUNNING_CHIP_ANIM) return
+
+ // skip status chip display time
+ advanceTimeBy(DISPLAY_LENGTH + 1)
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onSystemEventAnimationFinish(anyBoolean())
+ if (animationState == ANIMATING_OUT) return
+
+ // skip disappear animation
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+ }
+
+ private fun createAndScheduleFakePrivacyEvent(): OngoingPrivacyChip {
+ val privacyChip = OngoingPrivacyChip(mContext)
+ val fakePrivacyStatusEvent =
+ FakeStatusEvent(viewCreator = { privacyChip }, priority = 100, forceVisible = true)
+ systemStatusAnimationScheduler.onStatusEvent(fakePrivacyStatusEvent)
+ return privacyChip
+ }
+
+ private fun createAndScheduleFakeBatteryEvent(): BatteryStatusChip {
+ val batteryChip = BatteryStatusChip(mContext)
+ val fakeBatteryEvent =
+ FakeStatusEvent(viewCreator = { batteryChip }, priority = 50, forceVisible = false)
+ systemStatusAnimationScheduler.onStatusEvent(fakeBatteryEvent)
+ return batteryChip
+ }
+
+ private fun initializeSystemStatusAnimationScheduler(testScope: TestScope) {
+ systemStatusAnimationScheduler =
+ SystemStatusAnimationSchedulerImpl(
+ systemEventCoordinator,
+ chipAnimationController,
+ statusBarWindowController,
+ dumpManager,
+ systemClock,
+ CoroutineScope(StandardTestDispatcher(testScope.testScheduler))
+ )
+ // add a mock listener
+ systemStatusAnimationScheduler.addCallback(listener)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index 7fdcfb210804..2de57051d4f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.lockscreen
+import android.app.smartspace.SmartspaceAction
import android.app.smartspace.SmartspaceManager
import android.app.smartspace.SmartspaceSession
import android.app.smartspace.SmartspaceSession.OnTargetsAvailableListener
@@ -26,6 +27,7 @@ import android.content.pm.UserInfo
import android.database.ContentObserver
import android.graphics.drawable.Drawable
import android.net.Uri
+import android.os.Bundle
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
@@ -43,6 +45,7 @@ import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.WeatherData
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener
import com.android.systemui.settings.UserTracker
@@ -54,6 +57,7 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceP
import com.android.systemui.util.concurrency.FakeExecution
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argThat
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.settings.SecureSettings
@@ -69,6 +73,7 @@ import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.util.Optional
@@ -76,6 +81,13 @@ import java.util.concurrent.Executor
@SmallTest
class LockscreenSmartspaceControllerTest : SysuiTestCase() {
+ companion object {
+ const val SMARTSPACE_TIME_TOO_EARLY = 1000L
+ const val SMARTSPACE_TIME_JUST_RIGHT = 4000L
+ const val SMARTSPACE_TIME_TOO_LATE = 9000L
+ const val SMARTSPACE_CREATION_TIME = 1234L
+ const val SMARTSPACE_EXPIRY_TIME = 5678L
+ }
@Mock
private lateinit var featureFlags: FeatureFlags
@Mock
@@ -224,6 +236,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
smartspaceManager,
activityStarter,
falsingManager,
+ clock,
secureSettings,
userTracker,
contentResolver,
@@ -529,6 +542,190 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
}
@Test
+ fun testSessionListener_ifWeatherExtraMissing_thenWeatherDataNotSent() {
+ connectSession()
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeTarget(1, userHandlePrimary, isSensitive = true),
+ makeTarget(2, userHandlePrimary, featureType = SmartspaceTarget.FEATURE_WEATHER)
+
+ )
+ sessionListener.onTargetsAvailable(targets)
+ verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
+ }
+
+ @Test
+ fun testSessionListener_ifWeatherExtraIsMissingValues_thenWeatherDataNotSent() {
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeTarget(1, userHandlePrimary, isSensitive = true),
+ makeWeatherTargetWithExtras(
+ id = 2,
+ userHandle = userHandlePrimary,
+ description = null,
+ state = WeatherData.WeatherStateIcon.SUNNY.id,
+ temperature = "32",
+ useCelsius = null)
+
+ )
+
+ sessionListener.onTargetsAvailable(targets)
+
+ verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
+ }
+
+ @Test
+ fun testSessionListener_ifTooEarly_thenWeatherDataNotSent() {
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_TOO_EARLY)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeWeatherTargetWithExtras(
+ id = 1,
+ userHandle = userHandleManaged,
+ description = "Sunny",
+ state = WeatherData.WeatherStateIcon.SUNNY.id,
+ temperature = "32",
+ useCelsius = false)
+ )
+ sessionListener.onTargetsAvailable(targets)
+ verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
+ }
+
+ @Test
+ fun testSessionListener_ifOnTime_thenWeatherDataSent() {
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeWeatherTargetWithExtras(
+ id = 1,
+ userHandle = userHandleManaged,
+ description = "Snow Showers",
+ state = WeatherData.WeatherStateIcon.SNOW_SHOWERS_SNOW.id,
+ temperature = "-1",
+ useCelsius = false)
+ )
+ sessionListener.onTargetsAvailable(targets)
+ verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
+ w.description == "Snow Showers" &&
+ w.state == WeatherData.WeatherStateIcon.SNOW_SHOWERS_SNOW &&
+ w.temperature == -1 && !w.useCelsius
+ })
+ }
+
+ @Test
+ fun testSessionListener_ifTooLate_thenWeatherDataNotSent() {
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_TOO_LATE)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeWeatherTargetWithExtras(
+ id = 1,
+ userHandle = userHandleManaged,
+ description = "Sunny",
+ state = WeatherData.WeatherStateIcon.SUNNY.id,
+ temperature = "72",
+ useCelsius = false)
+ )
+ sessionListener.onTargetsAvailable(targets)
+ verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
+ }
+
+ @Test
+ fun testSessionListener_onlyFirstWeatherDataSent() {
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeWeatherTargetWithExtras(
+ id = 1,
+ userHandle = userHandleManaged,
+ description = "Sunny",
+ state = WeatherData.WeatherStateIcon.SUNNY.id,
+ temperature = "72",
+ useCelsius = false),
+ makeWeatherTargetWithExtras(
+ id = 2,
+ userHandle = userHandleManaged,
+ description = "Showers",
+ state = WeatherData.WeatherStateIcon.SHOWERS_RAIN.id,
+ temperature = "62",
+ useCelsius = true)
+ )
+ sessionListener.onTargetsAvailable(targets)
+ verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
+ w.description == "Sunny" &&
+ w.state == WeatherData.WeatherStateIcon.SUNNY &&
+ w.temperature == 72 && !w.useCelsius
+ })
+ }
+
+ @Test
+ fun testSessionListener_ifDecouplingEnabled_weatherDataUpdates() {
+ `when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(true)
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeTarget(1, userHandlePrimary, isSensitive = true),
+ makeTarget(2, userHandlePrimary),
+ makeTarget(3, userHandleManaged),
+ makeWeatherTargetWithExtras(
+ id = 4,
+ userHandle = userHandlePrimary,
+ description = "Flurries",
+ state = WeatherData.WeatherStateIcon.FLURRIES.id,
+ temperature = "0",
+ useCelsius = true)
+ )
+
+ sessionListener.onTargetsAvailable(targets)
+
+ verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
+ w.description == "Flurries" &&
+ w.state == WeatherData.WeatherStateIcon.FLURRIES &&
+ w.temperature == 0 && w.useCelsius
+ })
+ }
+
+ @Test
+ fun testSessionListener_ifDecouplingDisabled_weatherDataUpdates() {
+ `when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(false)
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeWeatherTargetWithExtras(
+ id = 1,
+ userHandle = userHandlePrimary,
+ description = "Sunny",
+ state = WeatherData.WeatherStateIcon.SUNNY.id,
+ temperature = "32",
+ useCelsius = false),
+ makeTarget(2, userHandlePrimary, isSensitive = true)
+ )
+
+ sessionListener.onTargetsAvailable(targets)
+
+ verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
+ w.description == "Sunny" &&
+ w.state == WeatherData.WeatherStateIcon.SUNNY &&
+ w.temperature == 32 && !w.useCelsius
+ })
+ }
+
+ @Test
fun testSettingsAreReloaded() {
// GIVEN a connected session where the privacy settings later flip to false
connectSession()
@@ -740,7 +937,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
return userInfo
}
- fun makeTarget(
+ private fun makeTarget(
id: Int,
userHandle: UserHandle,
isSensitive: Boolean = false,
@@ -755,6 +952,38 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
.build()
}
+ private fun makeWeatherTargetWithExtras(
+ id: Int,
+ userHandle: UserHandle,
+ description: String?,
+ state: Int?,
+ temperature: String?,
+ useCelsius: Boolean?
+ ): SmartspaceTarget {
+ val mockWeatherBundle = mock(Bundle::class.java).apply {
+ `when`(getString(WeatherData.DESCRIPTION_KEY)).thenReturn(description)
+ if (state != null)
+ `when`(getInt(eq(WeatherData.STATE_KEY), any())).thenReturn(state)
+ `when`(getString(WeatherData.TEMPERATURE_KEY)).thenReturn(temperature)
+ `when`(containsKey(WeatherData.USE_CELSIUS_KEY)).thenReturn(useCelsius != null)
+ if (useCelsius != null)
+ `when`(getBoolean(WeatherData.USE_CELSIUS_KEY)).thenReturn(useCelsius)
+ }
+
+ val mockBaseAction = mock(SmartspaceAction::class.java)
+ `when`(mockBaseAction.extras).thenReturn(mockWeatherBundle)
+ return SmartspaceTarget.Builder(
+ "targetWithWeatherExtras$id",
+ ComponentName("testpackage", "testclass$id"),
+ userHandle)
+ .setSensitive(false)
+ .setFeatureType(SmartspaceTarget.FEATURE_WEATHER)
+ .setBaseAction(mockBaseAction)
+ .setExpiryTimeMillis(SMARTSPACE_EXPIRY_TIME)
+ .setCreationTimeMillis(SMARTSPACE_CREATION_TIME)
+ .build()
+ }
+
private fun setAllowPrivateNotifications(user: UserHandle, value: Boolean) {
`when`(secureSettings.getIntForUser(
eq(PRIVATE_LOCKSCREEN_SETTING),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
new file mode 100644
index 000000000000..7a6779684fc5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
@@ -0,0 +1,111 @@
+/*
+ * 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.statusbar.notification
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.statusbar.StatusBarState
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NotificationWakeUpCoordinatorLoggerTest : SysuiTestCase() {
+
+ private val logBufferCounter = LogBufferCounter()
+ private lateinit var logger: NotificationWakeUpCoordinatorLogger
+
+ private fun verifyDidLog(times: Int) {
+ logBufferCounter.verifyDidLog(times)
+ }
+
+ @Before
+ fun setup() {
+ logger = NotificationWakeUpCoordinatorLogger(logBufferCounter.logBuffer)
+ }
+
+ @Test
+ fun setDozeAmountWillThrottleFractionalUpdates() {
+ logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(0)
+ logger.logSetDozeAmount(1f, 1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ }
+
+ @Test
+ fun setDozeAmountWillIncludeFractionalUpdatesWhenStateChanges() {
+ logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(0)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.KEYGUARD, changed = false)
+ verifyDidLog(1)
+ }
+
+ @Test
+ fun setDozeAmountWillIncludeFractionalUpdatesWhenSourceChanges() {
+ logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(0)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source2", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ }
+
+ class LogBufferCounter {
+ val recentLogs = mutableListOf<Pair<String, LogLevel>>()
+ val tracker =
+ object : LogcatEchoTracker {
+ override val logInBackgroundThread: Boolean = false
+ override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean = false
+ override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
+ recentLogs.add(tagName to level)
+ return true
+ }
+ }
+ val logBuffer =
+ LogBuffer(name = "test", maxSize = 1, logcatEchoTracker = tracker, systrace = false)
+
+ fun verifyDidLog(times: Int) {
+ assertThat(recentLogs).hasSize(times)
+ recentLogs.clear()
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
new file mode 100644
index 000000000000..95591a4b321c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
@@ -0,0 +1,163 @@
+/*
+ * 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.statusbar.notification
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
+import com.android.systemui.statusbar.policy.HeadsUpManager
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.anyFloat
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NotificationWakeUpCoordinatorTest : SysuiTestCase() {
+
+ private val dumpManager: DumpManager = mock()
+ private val headsUpManager: HeadsUpManager = mock()
+ private val statusBarStateController: StatusBarStateController = mock()
+ private val bypassController: KeyguardBypassController = mock()
+ private val dozeParameters: DozeParameters = mock()
+ private val screenOffAnimationController: ScreenOffAnimationController = mock()
+ private val logger: NotificationWakeUpCoordinatorLogger = mock()
+ private val stackScrollerController: NotificationStackScrollLayoutController = mock()
+
+ private lateinit var notificationWakeUpCoordinator: NotificationWakeUpCoordinator
+ private lateinit var statusBarStateCallback: StatusBarStateController.StateListener
+ private lateinit var bypassChangeCallback: KeyguardBypassController.OnBypassStateChangedListener
+
+ private var bypassEnabled: Boolean = false
+ private var statusBarState: Int = StatusBarState.KEYGUARD
+ private var dozeAmount: Float = 0f
+
+ private fun setBypassEnabled(enabled: Boolean) {
+ bypassEnabled = enabled
+ bypassChangeCallback.onBypassStateChanged(enabled)
+ }
+
+ private fun setStatusBarState(state: Int) {
+ statusBarState = state
+ statusBarStateCallback.onStateChanged(state)
+ }
+
+ private fun setDozeAmount(dozeAmount: Float) {
+ this.dozeAmount = dozeAmount
+ statusBarStateCallback.onDozeAmountChanged(dozeAmount, dozeAmount)
+ }
+
+ @Before
+ fun setup() {
+ whenever(bypassController.bypassEnabled).then { bypassEnabled }
+ whenever(statusBarStateController.state).then { statusBarState }
+ notificationWakeUpCoordinator =
+ NotificationWakeUpCoordinator(
+ dumpManager,
+ headsUpManager,
+ statusBarStateController,
+ bypassController,
+ dozeParameters,
+ screenOffAnimationController,
+ logger,
+ )
+ statusBarStateCallback = withArgCaptor {
+ verify(statusBarStateController).addCallback(capture())
+ }
+ bypassChangeCallback = withArgCaptor {
+ verify(bypassController).registerOnBypassStateChangedListener(capture())
+ }
+ notificationWakeUpCoordinator.setStackScroller(stackScrollerController)
+ }
+
+ @Test
+ fun setDozeToOneWillFullyHideNotifications() {
+ setDozeAmount(1f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 1f, hideAmount = 1f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
+ }
+
+ @Test
+ fun setDozeToZeroWillFullyShowNotifications() {
+ setDozeAmount(0f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ }
+
+ @Test
+ fun setDozeToOneThenZeroWillFullyShowNotifications() {
+ setDozeToOneWillFullyHideNotifications()
+ clearInvocations(stackScrollerController)
+ setDozeToZeroWillFullyShowNotifications()
+ }
+
+ @Test
+ fun setDozeToHalfWillHalfShowNotifications() {
+ setDozeAmount(0.5f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0.5f, hideAmount = 0.5f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ }
+
+ @Test
+ fun setDozeToZeroWithBypassWillFullyHideNotifications() {
+ bypassEnabled = true
+ setDozeAmount(0f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 01f, hideAmount = 1f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
+ }
+
+ @Test
+ fun disablingBypassWillShowNotifications() {
+ setDozeToZeroWithBypassWillFullyHideNotifications()
+ clearInvocations(stackScrollerController)
+ setBypassEnabled(false)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ }
+
+ @Test
+ fun switchingToShadeWithBypassEnabledWillShowNotifications() {
+ setDozeToZeroWithBypassWillFullyHideNotifications()
+ clearInvocations(stackScrollerController)
+ setStatusBarState(StatusBarState.SHADE)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ assertThat(notificationWakeUpCoordinator.statusBarState).isEqualTo(StatusBarState.SHADE)
+ }
+
+ private fun verifyStackScrollerDozeAndHideAmount(dozeAmount: Float, hideAmount: Float) {
+ // First verify that we did in-fact receive the correct values
+ verify(stackScrollerController).setDozeAmount(dozeAmount)
+ verify(stackScrollerController).setHideAmount(hideAmount, hideAmount)
+ // Now verify that there was just this ONE call to each of these methods
+ verify(stackScrollerController).setDozeAmount(anyFloat())
+ verify(stackScrollerController).setHideAmount(anyFloat(), anyFloat())
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 94e3e6cb5f8e..edb2965eabfa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -105,6 +105,7 @@ import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
+import org.mockito.stubbing.Answer;
import java.util.Arrays;
import java.util.Collection;
@@ -376,6 +377,90 @@ public class NotifCollectionTest extends SysuiTestCase {
}
@Test
+ public void testScheduleBuildNotificationListWhenChannelChanged() {
+ // GIVEN
+ final NotificationEntryBuilder neb = buildNotif(TEST_PACKAGE, 48);
+ final NotificationChannel channel = new NotificationChannel(
+ "channelId",
+ "channelName",
+ NotificationManager.IMPORTANCE_DEFAULT);
+ neb.setChannel(channel);
+
+ final NotifEvent notif = mNoMan.postNotif(neb);
+ final NotificationEntry entry = mCollectionListener.getEntry(notif.key);
+
+ when(mMainHandler.hasCallbacks(any())).thenReturn(false);
+
+ clearInvocations(mBuildListener);
+
+ // WHEN
+ mNotifHandler.onNotificationChannelModified(TEST_PACKAGE,
+ entry.getSbn().getUser(), channel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
+
+ // THEN
+ verify(mMainHandler).postDelayed(any(), eq(1000L));
+ }
+
+ @Test
+ public void testCancelScheduledBuildNotificationListEventWhenNotifUpdatedSynchronously() {
+ // GIVEN
+ final NotificationEntry entry1 = buildNotif(TEST_PACKAGE, 1)
+ .setGroup(mContext, "group_1")
+ .build();
+ final NotificationEntry entry2 = buildNotif(TEST_PACKAGE, 2)
+ .setGroup(mContext, "group_1")
+ .setContentTitle(mContext, "New version")
+ .build();
+ final NotificationEntry entry3 = buildNotif(TEST_PACKAGE, 3)
+ .setGroup(mContext, "group_1")
+ .build();
+
+ final List<CoalescedEvent> entriesToBePosted = Arrays.asList(
+ new CoalescedEvent(entry1.getKey(), 0, entry1.getSbn(), entry1.getRanking(), null),
+ new CoalescedEvent(entry2.getKey(), 1, entry2.getSbn(), entry2.getRanking(), null),
+ new CoalescedEvent(entry3.getKey(), 2, entry3.getSbn(), entry3.getRanking(), null)
+ );
+
+ when(mMainHandler.hasCallbacks(any())).thenReturn(true);
+
+ // WHEN
+ mNotifHandler.onNotificationBatchPosted(entriesToBePosted);
+
+ // THEN
+ verify(mMainHandler).removeCallbacks(any());
+ }
+
+ @Test
+ public void testBuildNotificationListWhenChannelChanged() {
+ // GIVEN
+ final NotificationEntryBuilder neb = buildNotif(TEST_PACKAGE, 48);
+ final NotificationChannel channel = new NotificationChannel(
+ "channelId",
+ "channelName",
+ NotificationManager.IMPORTANCE_DEFAULT);
+ neb.setChannel(channel);
+
+ final NotifEvent notif = mNoMan.postNotif(neb);
+ final NotificationEntry entry = mCollectionListener.getEntry(notif.key);
+
+ when(mMainHandler.hasCallbacks(any())).thenReturn(false);
+ when(mMainHandler.postDelayed(any(), eq(1000L))).thenAnswer((Answer) invocation -> {
+ final Runnable runnable = invocation.getArgument(0);
+ runnable.run();
+ return null;
+ });
+
+ clearInvocations(mBuildListener);
+
+ // WHEN
+ mNotifHandler.onNotificationChannelModified(TEST_PACKAGE,
+ entry.getSbn().getUser(), channel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
+
+ // THEN
+ verifyBuiltList(List.of(entry));
+ }
+
+ @Test
public void testRankingsAreUpdatedForOtherNotifs() {
// GIVEN a collection with one notif
NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
index bd039031cecc..33a838ed5183 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
@@ -20,6 +20,7 @@ import android.app.Notification
import android.app.StatsManager
import android.graphics.Bitmap
import android.graphics.drawable.Icon
+import android.stats.sysui.NotificationEnums
import android.testing.AndroidTestingRunner
import android.util.StatsEvent
import androidx.test.filters.SmallTest
@@ -31,10 +32,12 @@ import com.android.systemui.util.concurrency.FakeExecutor
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.Expect
import com.google.common.truth.Truth.assertThat
import java.lang.RuntimeException
import kotlinx.coroutines.Dispatchers
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
@@ -45,6 +48,8 @@ import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
class NotificationMemoryLoggerTest : SysuiTestCase() {
+ @Rule @JvmField val expect = Expect.create()
+
private val bgExecutor = FakeExecutor(FakeSystemClock())
private val immediate = Dispatchers.Main.immediate
@@ -132,6 +137,123 @@ class NotificationMemoryLoggerTest : SysuiTestCase() {
.isEqualTo(StatsManager.PULL_SKIP)
}
+ @Test
+ fun aggregateMemoryUsageData_returnsCorrectlyAggregatedSamePackageData() {
+ val usage = getPresetMemoryUsages()
+ val aggregateUsage = aggregateMemoryUsageData(usage)
+
+ assertThat(aggregateUsage).hasSize(3)
+ assertThat(aggregateUsage)
+ .containsKey(Pair("package 1", NotificationEnums.STYLE_BIG_PICTURE))
+
+ // Aggregated fields
+ val aggregatedData =
+ aggregateUsage[Pair("package 1", NotificationEnums.STYLE_BIG_PICTURE)]!!
+ val presetUsage1 = usage[0]
+ val presetUsage2 = usage[1]
+ assertAggregatedData(
+ aggregatedData,
+ 2,
+ 2,
+ smallIconObject =
+ presetUsage1.objectUsage.smallIcon + presetUsage2.objectUsage.smallIcon,
+ smallIconBitmapCount = 2,
+ largeIconObject =
+ presetUsage1.objectUsage.largeIcon + presetUsage2.objectUsage.largeIcon,
+ largeIconBitmapCount = 2,
+ bigPictureObject =
+ presetUsage1.objectUsage.bigPicture + presetUsage2.objectUsage.bigPicture,
+ bigPictureBitmapCount = 2,
+ extras = presetUsage1.objectUsage.extras + presetUsage2.objectUsage.extras,
+ extenders = presetUsage1.objectUsage.extender + presetUsage2.objectUsage.extender,
+ // Only totals need to be summarized.
+ smallIconViews =
+ presetUsage1.viewUsage[0].smallIcon + presetUsage2.viewUsage[0].smallIcon,
+ largeIconViews =
+ presetUsage1.viewUsage[0].largeIcon + presetUsage2.viewUsage[0].largeIcon,
+ systemIconViews =
+ presetUsage1.viewUsage[0].systemIcons + presetUsage2.viewUsage[0].systemIcons,
+ styleViews = presetUsage1.viewUsage[0].style + presetUsage2.viewUsage[0].style,
+ customViews =
+ presetUsage1.viewUsage[0].customViews + presetUsage2.viewUsage[0].customViews,
+ softwareBitmaps =
+ presetUsage1.viewUsage[0].softwareBitmapsPenalty +
+ presetUsage2.viewUsage[0].softwareBitmapsPenalty,
+ seenCount = 0
+ )
+ }
+
+ @Test
+ fun aggregateMemoryUsageData_correctlySeparatesDifferentStyles() {
+ val usage = getPresetMemoryUsages()
+ val aggregateUsage = aggregateMemoryUsageData(usage)
+
+ assertThat(aggregateUsage).hasSize(3)
+ assertThat(aggregateUsage)
+ .containsKey(Pair("package 1", NotificationEnums.STYLE_BIG_PICTURE))
+ assertThat(aggregateUsage).containsKey(Pair("package 1", NotificationEnums.STYLE_BIG_TEXT))
+
+ // Different style should be separate
+ val separateStyleData =
+ aggregateUsage[Pair("package 1", NotificationEnums.STYLE_BIG_TEXT)]!!
+ val presetUsage = usage[2]
+ assertAggregatedData(
+ separateStyleData,
+ 1,
+ 1,
+ presetUsage.objectUsage.smallIcon,
+ 1,
+ presetUsage.objectUsage.largeIcon,
+ 1,
+ presetUsage.objectUsage.bigPicture,
+ 1,
+ presetUsage.objectUsage.extras,
+ presetUsage.objectUsage.extender,
+ presetUsage.viewUsage[0].smallIcon,
+ presetUsage.viewUsage[0].largeIcon,
+ presetUsage.viewUsage[0].systemIcons,
+ presetUsage.viewUsage[0].style,
+ presetUsage.viewUsage[0].customViews,
+ presetUsage.viewUsage[0].softwareBitmapsPenalty,
+ 0
+ )
+ }
+
+ @Test
+ fun aggregateMemoryUsageData_correctlySeparatesDifferentProcess() {
+ val usage = getPresetMemoryUsages()
+ val aggregateUsage = aggregateMemoryUsageData(usage)
+
+ assertThat(aggregateUsage).hasSize(3)
+ assertThat(aggregateUsage)
+ .containsKey(Pair("package 2", NotificationEnums.STYLE_BIG_PICTURE))
+
+ // Different UID/package should also be separate
+ val separatePackageData =
+ aggregateUsage[Pair("package 2", NotificationEnums.STYLE_BIG_PICTURE)]!!
+ val presetUsage = usage[3]
+ assertAggregatedData(
+ separatePackageData,
+ 1,
+ 1,
+ presetUsage.objectUsage.smallIcon,
+ 1,
+ presetUsage.objectUsage.largeIcon,
+ 1,
+ presetUsage.objectUsage.bigPicture,
+ 1,
+ presetUsage.objectUsage.extras,
+ presetUsage.objectUsage.extender,
+ presetUsage.viewUsage[0].smallIcon,
+ presetUsage.viewUsage[0].largeIcon,
+ presetUsage.viewUsage[0].systemIcons,
+ presetUsage.viewUsage[0].style,
+ presetUsage.viewUsage[0].customViews,
+ presetUsage.viewUsage[0].softwareBitmapsPenalty,
+ 0
+ )
+ }
+
private fun createLoggerWithNotifications(
notifications: List<Notification>
): NotificationMemoryLogger {
@@ -143,4 +265,182 @@ class NotificationMemoryLoggerTest : SysuiTestCase() {
whenever(pipeline.allNotifs).thenReturn(notifications)
return NotificationMemoryLogger(pipeline, statsManager, immediate, bgExecutor)
}
+
+ /**
+ * Short hand for making sure the passed NotificationMemoryUseAtomBuilder object contains
+ * expected values.
+ */
+ private fun assertAggregatedData(
+ value: NotificationMemoryLogger.NotificationMemoryUseAtomBuilder,
+ count: Int,
+ countWithInflatedViews: Int,
+ smallIconObject: Int,
+ smallIconBitmapCount: Int,
+ largeIconObject: Int,
+ largeIconBitmapCount: Int,
+ bigPictureObject: Int,
+ bigPictureBitmapCount: Int,
+ extras: Int,
+ extenders: Int,
+ smallIconViews: Int,
+ largeIconViews: Int,
+ systemIconViews: Int,
+ styleViews: Int,
+ customViews: Int,
+ softwareBitmaps: Int,
+ seenCount: Int
+ ) {
+ expect.withMessage("count").that(value.count).isEqualTo(count)
+ expect
+ .withMessage("countWithInflatedViews")
+ .that(value.countWithInflatedViews)
+ .isEqualTo(countWithInflatedViews)
+ expect.withMessage("smallIconObject").that(value.smallIconObject).isEqualTo(smallIconObject)
+ expect
+ .withMessage("smallIconBitmapCount")
+ .that(value.smallIconBitmapCount)
+ .isEqualTo(smallIconBitmapCount)
+ expect.withMessage("largeIconObject").that(value.largeIconObject).isEqualTo(largeIconObject)
+ expect
+ .withMessage("largeIconBitmapCount")
+ .that(value.largeIconBitmapCount)
+ .isEqualTo(largeIconBitmapCount)
+ expect
+ .withMessage("bigPictureObject")
+ .that(value.bigPictureObject)
+ .isEqualTo(bigPictureObject)
+ expect
+ .withMessage("bigPictureBitmapCount")
+ .that(value.bigPictureBitmapCount)
+ .isEqualTo(bigPictureBitmapCount)
+ expect.withMessage("extras").that(value.extras).isEqualTo(extras)
+ expect.withMessage("extenders").that(value.extenders).isEqualTo(extenders)
+ expect.withMessage("smallIconViews").that(value.smallIconViews).isEqualTo(smallIconViews)
+ expect.withMessage("largeIconViews").that(value.largeIconViews).isEqualTo(largeIconViews)
+ expect.withMessage("systemIconViews").that(value.systemIconViews).isEqualTo(systemIconViews)
+ expect.withMessage("styleViews").that(value.styleViews).isEqualTo(styleViews)
+ expect.withMessage("customViews").that(value.customViews).isEqualTo(customViews)
+ expect.withMessage("softwareBitmaps").that(value.softwareBitmaps).isEqualTo(softwareBitmaps)
+ expect.withMessage("seenCount").that(value.seenCount).isEqualTo(seenCount)
+ }
+
+ /** Generates a static set of [NotificationMemoryUsage] objects. */
+ private fun getPresetMemoryUsages() =
+ listOf(
+ // A pair of notifications that have to be aggregated, same UID and style
+ NotificationMemoryUsage(
+ "package 1",
+ 384,
+ "key1",
+ Notification.Builder(context).setStyle(Notification.BigPictureStyle()).build(),
+ NotificationObjectUsage(
+ 23,
+ 45,
+ 67,
+ NotificationEnums.STYLE_BIG_PICTURE,
+ 12,
+ 483,
+ 4382,
+ true
+ ),
+ listOf(
+ NotificationViewUsage(ViewType.TOTAL, 493, 584, 4833, 584, 4888, 5843),
+ NotificationViewUsage(
+ ViewType.PRIVATE_CONTRACTED_VIEW,
+ 100,
+ 250,
+ 300,
+ 594,
+ 6000,
+ 5843
+ )
+ )
+ ),
+ NotificationMemoryUsage(
+ "package 1",
+ 384,
+ "key2",
+ Notification.Builder(context).setStyle(Notification.BigPictureStyle()).build(),
+ NotificationObjectUsage(
+ 77,
+ 54,
+ 34,
+ NotificationEnums.STYLE_BIG_PICTURE,
+ 77,
+ 432,
+ 2342,
+ true
+ ),
+ listOf(
+ NotificationViewUsage(ViewType.TOTAL, 3245, 1234, 7653, 543, 765, 7655),
+ NotificationViewUsage(
+ ViewType.PRIVATE_CONTRACTED_VIEW,
+ 160,
+ 350,
+ 300,
+ 5544,
+ 66500,
+ 5433
+ )
+ )
+ ),
+ // Different style is different aggregation
+ NotificationMemoryUsage(
+ "package 1",
+ 384,
+ "key2",
+ Notification.Builder(context).setStyle(Notification.BigTextStyle()).build(),
+ NotificationObjectUsage(
+ 77,
+ 54,
+ 34,
+ NotificationEnums.STYLE_BIG_TEXT,
+ 77,
+ 432,
+ 2342,
+ true
+ ),
+ listOf(
+ NotificationViewUsage(ViewType.TOTAL, 3245, 1234, 7653, 543, 765, 7655),
+ NotificationViewUsage(
+ ViewType.PRIVATE_CONTRACTED_VIEW,
+ 160,
+ 350,
+ 300,
+ 5544,
+ 66500,
+ 5433
+ )
+ )
+ ),
+ // Different package is also different aggregation
+ NotificationMemoryUsage(
+ "package 2",
+ 684,
+ "key2",
+ Notification.Builder(context).setStyle(Notification.BigPictureStyle()).build(),
+ NotificationObjectUsage(
+ 32,
+ 654,
+ 234,
+ NotificationEnums.STYLE_BIG_PICTURE,
+ 211,
+ 776,
+ 435,
+ true
+ ),
+ listOf(
+ NotificationViewUsage(ViewType.TOTAL, 4355, 6543, 4322, 5435, 6546, 65485),
+ NotificationViewUsage(
+ ViewType.PRIVATE_CONTRACTED_VIEW,
+ 6546,
+ 7657,
+ 4353,
+ 6546,
+ 76575,
+ 54654
+ )
+ )
+ )
+ )
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 9e23d548e5b5..957b0f10ec1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -103,6 +103,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
FakeFeatureFlags fakeFeatureFlags = new FakeFeatureFlags();
fakeFeatureFlags.set(Flags.NOTIFICATION_ANIMATE_BIG_PICTURE, true);
+ fakeFeatureFlags.set(Flags.SENSITIVE_REVEAL_ANIM, false);
mNotificationTestHelper.setFeatureFlags(fakeFeatureFlags);
}
@@ -402,17 +403,6 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
}
@Test
- public void testIsBlockingHelperShowing_isCorrectlyUpdated() throws Exception {
- ExpandableNotificationRow group = mNotificationTestHelper.createGroup();
-
- group.setBlockingHelperShowing(true);
- assertTrue(group.isBlockingHelperShowing());
-
- group.setBlockingHelperShowing(false);
- assertFalse(group.isBlockingHelperShowing());
- }
-
- @Test
public void testGetNumUniqueChildren_defaultChannel() throws Exception {
ExpandableNotificationRow groupRow = mNotificationTestHelper.createGroup();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index d7ac6b41ee78..3d8a74466a5c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -117,7 +117,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
@Mock private NotificationPresenter mPresenter;
@Mock private NotificationActivityStarter mNotificationActivityStarter;
@Mock private NotificationListContainer mNotificationListContainer;
- @Mock private NotificationInfo.CheckSaveListener mCheckSaveListener;
@Mock private OnSettingsClickListener mOnSettingsClickListener;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private CentralSurfaces mCentralSurfaces;
@@ -173,7 +172,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
// Test doesn't support animation since the guts view is not attached.
doNothing().when(guts).openControls(
- eq(true) /* shouldDoCircularReveal */,
anyInt(),
anyInt(),
anyBoolean(),
@@ -190,7 +188,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
assertEquals(View.INVISIBLE, guts.getVisibility());
mTestableLooper.processAllMessages();
verify(guts).openControls(
- eq(true),
anyInt(),
anyInt(),
anyBoolean(),
@@ -213,7 +210,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
// Test doesn't support animation since the guts view is not attached.
doNothing().when(guts).openControls(
- eq(true) /* shouldDoCircularReveal */,
anyInt(),
anyInt(),
anyBoolean(),
@@ -237,7 +233,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
assertTrue(mGutsManager.openGutsInternal(row, 0, 0, menuItem));
mTestableLooper.processAllMessages();
verify(guts).openControls(
- eq(true),
anyInt(),
anyInt(),
anyBoolean(),
@@ -379,7 +374,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
public void testInitializeNotificationInfoView_PassesAlongProvisionedState() throws Exception {
NotificationInfo notificationInfoView = mock(NotificationInfo.class);
ExpandableNotificationRow row = spy(mHelper.createRow());
- row.setBlockingHelperShowing(false);
modifyRanking(row.getEntry())
.setUserSentiment(USER_SENTIMENT_NEGATIVE)
.build();
@@ -414,7 +408,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
public void testInitializeNotificationInfoView_withInitialAction() throws Exception {
NotificationInfo notificationInfoView = mock(NotificationInfo.class);
ExpandableNotificationRow row = spy(mHelper.createRow());
- row.setBlockingHelperShowing(true);
modifyRanking(row.getEntry())
.setUserSentiment(USER_SENTIMENT_NEGATIVE)
.build();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
index e696c8738d72..fdfb4f4612fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
@@ -76,7 +76,7 @@ class NotificationGutsTest : SysuiTestCase() {
fun openControls() {
guts.gutsContent = gutsContent
- guts.openControls(true, 0, 0, false, null)
+ guts.openControls(0, 0, false, null)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt
index 87f4c323b7cc..09382ec1945e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt
@@ -20,6 +20,8 @@ import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.util.mockito.mock
@@ -39,6 +41,8 @@ class AmbientStateTest : SysuiTestCase() {
private val sectionProvider = StackScrollAlgorithm.SectionProvider { _, _ -> false }
private val bypassController = StackScrollAlgorithm.BypassController { false }
private val statusBarKeyguardViewManager = mock<StatusBarKeyguardViewManager>()
+ private val largeScreenShadeInterpolator = mock<LargeScreenShadeInterpolator>()
+ private val featureFlags = mock<FeatureFlags>()
private lateinit var sut: AmbientState
@@ -51,6 +55,8 @@ class AmbientStateTest : SysuiTestCase() {
sectionProvider,
bypassController,
statusBarKeyguardViewManager,
+ largeScreenShadeInterpolator,
+ featureFlags
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
index 9d759c4b6016..b1d3daa27eae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
@@ -7,6 +7,9 @@ import androidx.test.filters.SmallTest
import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ShadeInterpolation
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.notification.LegacySourceType
@@ -21,7 +24,9 @@ import junit.framework.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.Mock
import org.mockito.Mockito.mock
+import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when` as whenever
/**
@@ -32,6 +37,9 @@ import org.mockito.Mockito.`when` as whenever
@RunWithLooper
class NotificationShelfTest : SysuiTestCase() {
+ @Mock private lateinit var largeScreenShadeInterpolator: LargeScreenShadeInterpolator
+ @Mock private lateinit var flags: FeatureFlags
+
private val shelf = NotificationShelf(
context,
/* attrs */ null,
@@ -50,8 +58,12 @@ class NotificationShelfTest : SysuiTestCase() {
@Before
fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(ambientState.largeScreenShadeInterpolator).thenReturn(largeScreenShadeInterpolator)
+ whenever(ambientState.featureFlags).thenReturn(flags)
shelf.bind(ambientState, /* hostLayoutController */ hostLayoutController)
shelf.layout(/* left */ 0, /* top */ 0, /* right */ 30, /* bottom */5)
+ whenever(ambientState.isSmallScreen).thenReturn(true)
}
@Test
@@ -295,7 +307,35 @@ class NotificationShelfTest : SysuiTestCase() {
fun updateState_expansionChanging_shelfAlphaUpdated() {
updateState_expansionChanging_shelfAlphaUpdated(
expansionFraction = 0.6f,
- expectedAlpha = ShadeInterpolation.getContentAlpha(0.6f)
+ expectedAlpha = ShadeInterpolation.getContentAlpha(0.6f),
+ )
+ }
+
+ @Test
+ fun updateState_flagTrue_largeScreen_expansionChanging_shelfAlphaUpdated_largeScreenValue() {
+ val expansionFraction = 0.6f
+ whenever(flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)).thenReturn(true)
+ whenever(ambientState.isSmallScreen).thenReturn(false)
+ whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
+ .thenReturn(0.123f)
+
+ updateState_expansionChanging_shelfAlphaUpdated(
+ expansionFraction = expansionFraction,
+ expectedAlpha = 0.123f
+ )
+ }
+
+ @Test
+ fun updateState_flagFalse_largeScreen_expansionChanging_shelfAlphaUpdated_standardValue() {
+ val expansionFraction = 0.6f
+ whenever(flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)).thenReturn(false)
+ whenever(ambientState.isSmallScreen).thenReturn(false)
+ whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
+ .thenReturn(0.123f)
+
+ updateState_expansionChanging_shelfAlphaUpdated(
+ expansionFraction = expansionFraction,
+ expectedAlpha = ShadeInterpolation.getContentAlpha(expansionFraction)
)
}
@@ -305,7 +345,17 @@ class NotificationShelfTest : SysuiTestCase() {
updateState_expansionChanging_shelfAlphaUpdated(
expansionFraction = 0.95f,
- expectedAlpha = aboutToShowBouncerProgress(0.95f)
+ expectedAlpha = aboutToShowBouncerProgress(0.95f),
+ )
+ }
+
+ @Test
+ fun updateState_largeScreen_expansionChangingWhileBouncerInTransit_bouncerInterpolatorUsed() {
+ whenever(ambientState.isBouncerInTransit).thenReturn(true)
+
+ updateState_expansionChanging_shelfAlphaUpdated(
+ expansionFraction = 0.95f,
+ expectedAlpha = aboutToShowBouncerProgress(0.95f),
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 9f6f082d07c4..45ae96c10345 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -52,7 +52,6 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeController;
-import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
@@ -135,7 +134,6 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
@Mock private StackStateLogger mStackLogger;
@Mock private NotificationStackScrollLogger mLogger;
@Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
- @Mock private ShadeTransitionController mShadeTransitionController;
@Mock private FeatureFlags mFeatureFlags;
@Mock private NotificationTargetsHelper mNotificationTargetsHelper;
@Mock private SecureSettings mSecureSettings;
@@ -183,7 +181,6 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
mNotifPipelineFlags,
mNotifCollection,
mLockscreenShadeTransitionController,
- mShadeTransitionController,
mUiEventLogger,
mRemoteInputManager,
mVisibilityLocationProviderDelegator,
@@ -413,6 +410,37 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
verify(mNotificationStackScrollLayout).updateEmptyShadeView(anyBoolean(), anyBoolean());
}
+ @Test
+ public void testAttach_updatesViewStatusBarState() {
+ // GIVEN: Controller is attached
+ mController.attach(mNotificationStackScrollLayout);
+ ArgumentCaptor<StatusBarStateController.StateListener> captor =
+ ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
+ verify(mSysuiStatusBarStateController).addCallback(captor.capture(), anyInt());
+ StatusBarStateController.StateListener stateListener = captor.getValue();
+
+ // WHEN: StatusBarState changes to SHADE
+ when(mSysuiStatusBarStateController.getState()).thenReturn(SHADE);
+ stateListener.onStateChanged(SHADE);
+
+ // THEN: NSSL is updated with the current state
+ verify(mNotificationStackScrollLayout).setStatusBarState(SHADE);
+
+ // WHEN: Controller is detached
+ mController.mOnAttachStateChangeListener
+ .onViewDetachedFromWindow(mNotificationStackScrollLayout);
+
+ // WHEN: StatusBarState changes to KEYGUARD
+ when(mSysuiStatusBarStateController.getState()).thenReturn(KEYGUARD);
+
+ // WHEN: Controller is re-attached
+ mController.mOnAttachStateChangeListener
+ .onViewAttachedToWindow(mNotificationStackScrollLayout);
+
+ // THEN: NSSL is updated with the current state
+ verify(mNotificationStackScrollLayout).setStatusBarState(KEYGUARD);
+ }
+
private LogMaker logMatcher(int category, int type) {
return argThat(new LogMatcher(category, type));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index dd7143ae7e16..7153e59fff37 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.stack;
import static android.view.View.GONE;
+import static android.view.WindowInsets.Type.ime;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
@@ -46,6 +47,7 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.graphics.Insets;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -54,6 +56,8 @@ import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.WindowInsetsAnimation;
import android.widget.TextView;
import androidx.test.annotation.UiThreadTest;
@@ -64,7 +68,9 @@ import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.shade.ShadeController;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationShelfController;
@@ -91,6 +97,8 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.util.ArrayList;
+
/**
* Tests for {@link NotificationStackScrollLayout}.
*/
@@ -123,6 +131,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Mock private NotificationShelf mNotificationShelf;
@Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ @Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
+ @Mock private FeatureFlags mFeatureFlags;
@Before
@UiThreadTest
@@ -136,7 +146,10 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mDumpManager,
mNotificationSectionsManager,
mBypassController,
- mStatusBarKeyguardViewManager));
+ mStatusBarKeyguardViewManager,
+ mLargeScreenShadeInterpolator,
+ mFeatureFlags
+ ));
// Inject dependencies before initializing the layout
mDependency.injectTestDependency(SysuiStatusBarStateController.class, mBarState);
@@ -843,6 +856,19 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
verify(mEmptyShadeView).setFooterText(not(0));
}
+ @Test
+ public void testWindowInsetAnimationProgress_updatesBottomInset() {
+ int bottomImeInset = 100;
+ mStackScrollerInternal.setAnimatedInsetsEnabled(true);
+ WindowInsets windowInsets = new WindowInsets.Builder()
+ .setInsets(ime(), Insets.of(0, 0, 0, bottomImeInset)).build();
+ ArrayList<WindowInsetsAnimation> windowInsetsAnimations = new ArrayList<>();
+ mStackScrollerInternal
+ .dispatchWindowInsetsAnimationProgress(windowInsets, windowInsetsAnimations);
+
+ assertEquals(bottomImeInset, mStackScrollerInternal.mBottomInset);
+ }
+
private void setBarStateForTest(int state) {
// Can't inject this through the listener or we end up on the actual implementation
// rather than the mock because the spy just coppied the anonymous inner /shruggie.
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 680a32375988..78da78269ac4 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
@@ -20,6 +20,7 @@ import static junit.framework.Assert.assertTrue;
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.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -227,14 +228,154 @@ public class NotificationSwipeHelperTest extends SysuiTestCase {
}
@Test
- public void testHandleUpEvent_menuRow() {
- when(mSwipeHelper.getCurrentMenuRow()).thenReturn(mMenuRow);
- doNothing().when(mSwipeHelper).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+ public void testHandleUpEvent_menuRowWithoutMenu_dismiss() {
+ doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+ doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithoutMenu_snapback() {
+ doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+ doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+ verify(mMenuRow, times(1)).onSnapClosed();
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithOpenMenu_dismissed() {
+ doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+ doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithOpenMenu_snapback() {
+ doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+ doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+ verify(mMenuRow, times(1)).onSnapClosed();
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithClosedMenu_dismissed() {
+ doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+ doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(false);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
assertTrue("Menu row exists",
mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
verify(mMenuRow, times(1)).onTouchEnd();
- verify(mSwipeHelper, times(1)).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithClosedMenu_snapback() {
+ doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+ doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(false);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+ verify(mMenuRow, times(1)).onSnapClosed();
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture() {
+ doReturn(false).when(mSwipeHelper).isFalseGesture();
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ doReturn(true).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertTrue("Should be a dismiss gesture", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture_falseGesture() {
+ doReturn(true).when(mSwipeHelper).isFalseGesture();
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ doReturn(true).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertFalse("False gesture should stop dismissal", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture_farEnough() {
+ doReturn(false).when(mSwipeHelper).isFalseGesture();
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ doReturn(false).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertTrue("Should be a dismissal", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture_notFarOrFastEnough() {
+ doReturn(false).when(mSwipeHelper).isFalseGesture();
+ doReturn(false).when(mSwipeHelper).swipedFarEnough();
+ doReturn(false).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertFalse("Should not be a dismissal", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
}
@Test
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 4d9db8c28e07..7f20f1e53d97 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
@@ -8,6 +8,9 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ShadeInterpolation.getContentAlpha
import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
import com.android.systemui.statusbar.EmptyShadeView
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.StatusBarState
@@ -15,11 +18,13 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Expect
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.mockito.Mockito.any
import org.mockito.Mockito.eq
@@ -30,12 +35,19 @@ import org.mockito.Mockito.`when` as whenever
@SmallTest
class StackScrollAlgorithmTest : SysuiTestCase() {
+
+ @JvmField @Rule
+ var expect: Expect = Expect.create()
+
+ private val largeScreenShadeInterpolator = mock<LargeScreenShadeInterpolator>()
+
private val hostView = FrameLayout(context)
private val stackScrollAlgorithm = StackScrollAlgorithm(context, hostView)
private val notificationRow = mock<ExpandableNotificationRow>()
private val dumpManager = mock<DumpManager>()
private val mStatusBarKeyguardViewManager = mock<StatusBarKeyguardViewManager>()
private val notificationShelf = mock<NotificationShelf>()
+ private val featureFlags = mock<FeatureFlags>()
private val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
}
@@ -44,8 +56,10 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
dumpManager,
/* sectionProvider */ { _, _ -> false },
/* bypassController */ { false },
- mStatusBarKeyguardViewManager
- )
+ mStatusBarKeyguardViewManager,
+ largeScreenShadeInterpolator,
+ featureFlags,
+ )
private val testableResources = mContext.getOrCreateTestableResources()
@@ -59,6 +73,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
fun setUp() {
whenever(notificationShelf.viewState).thenReturn(ExpandableViewState())
whenever(notificationRow.viewState).thenReturn(ExpandableViewState())
+ ambientState.isSmallScreen = true
hostView.addView(notificationRow)
}
@@ -145,11 +160,46 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
}
@Test
- fun resetViewStates_expansionChangingWhileBouncerInTransit_notificationAlphaUpdated() {
+ fun resetViewStates_flagTrue_largeScreen_expansionChanging_alphaUpdated_largeScreenValue() {
+ val expansionFraction = 0.6f
+ val surfaceAlpha = 123f
+ ambientState.isSmallScreen = false
+ whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+ .thenReturn(true)
+ whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(false)
+ whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
+ .thenReturn(surfaceAlpha)
+
+ resetViewStates_expansionChanging_notificationAlphaUpdated(
+ expansionFraction = expansionFraction,
+ expectedAlpha = surfaceAlpha,
+ )
+ }
+
+ @Test
+ fun resetViewStates_flagFalse_largeScreen_expansionChanging_alphaUpdated_standardValue() {
+ val expansionFraction = 0.6f
+ val surfaceAlpha = 123f
+ ambientState.isSmallScreen = false
+ whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+ .thenReturn(false)
+ whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(false)
+ whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
+ .thenReturn(surfaceAlpha)
+
+ resetViewStates_expansionChanging_notificationAlphaUpdated(
+ expansionFraction = expansionFraction,
+ expectedAlpha = getContentAlpha(expansionFraction),
+ )
+ }
+
+ @Test
+ fun expansionChanging_largeScreen_bouncerInTransit_alphaUpdated_bouncerValues() {
+ ambientState.isSmallScreen = false
whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(true)
resetViewStates_expansionChanging_notificationAlphaUpdated(
expansionFraction = 0.95f,
- expectedAlpha = aboutToShowBouncerProgress(0.95f)
+ expectedAlpha = aboutToShowBouncerProgress(0.95f),
)
}
@@ -696,7 +746,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
private fun resetViewStates_expansionChanging_notificationAlphaUpdated(
expansionFraction: Float,
- expectedAlpha: Float
+ expectedAlpha: Float,
) {
ambientState.isExpansionChanging = true
ambientState.expansionFraction = expansionFraction
@@ -704,7 +754,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
- assertThat(notificationRow.viewState.alpha).isEqualTo(expectedAlpha)
+ expect.that(notificationRow.viewState.alpha).isEqualTo(expectedAlpha)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index f568547d3b59..e680a4ec19d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -53,7 +53,7 @@ import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.AutoAddTracker;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.ReduceBrightColorsController;
import com.android.systemui.qs.SettingObserver;
import com.android.systemui.qs.external.CustomTile;
@@ -104,7 +104,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
private static final int USER = 0;
- @Mock private QSTileHost mQsTileHost;
+ @Mock private QSHost mQsHost;
@Mock private AutoAddTracker mAutoAddTracker;
@Mock private CastController mCastController;
@Mock private HotspotController mHotspotController;
@@ -144,7 +144,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
R.string.safety_quick_settings_tile_class, TEST_CUSTOM_SAFETY_CLASS);
when(mAutoAddTrackerBuilder.build()).thenReturn(mAutoAddTracker);
- when(mQsTileHost.getUserContext()).thenReturn(mUserContext);
+ when(mQsHost.getUserContext()).thenReturn(mUserContext);
when(mUserContext.getUser()).thenReturn(UserHandle.of(USER));
mPackageManager = Mockito.spy(mContext.getPackageManager());
when(mPackageManager.getPermissionControllerPackageName())
@@ -174,7 +174,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
WalletController walletController,
SafetyController safetyController,
@Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) {
- return new AutoTileManager(context, autoAddTrackerBuilder, mQsTileHost,
+ return new AutoTileManager(context, autoAddTrackerBuilder, mQsHost,
Handler.createAsync(TestableLooper.get(this).getLooper()),
mSecureSettings,
hotspotController,
@@ -359,7 +359,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
return;
}
mAutoTileManager.mNightDisplayCallback.onActivated(true);
- verify(mQsTileHost).addTile("night");
+ verify(mQsHost).addTile("night");
}
@Test
@@ -368,7 +368,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
return;
}
mAutoTileManager.mNightDisplayCallback.onActivated(false);
- verify(mQsTileHost, never()).addTile("night");
+ verify(mQsHost, never()).addTile("night");
}
@Test
@@ -378,7 +378,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
}
mAutoTileManager.mNightDisplayCallback.onAutoModeChanged(
ColorDisplayManager.AUTO_MODE_TWILIGHT);
- verify(mQsTileHost).addTile("night");
+ verify(mQsHost).addTile("night");
}
@Test
@@ -388,7 +388,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
}
mAutoTileManager.mNightDisplayCallback.onAutoModeChanged(
ColorDisplayManager.AUTO_MODE_CUSTOM_TIME);
- verify(mQsTileHost).addTile("night");
+ verify(mQsHost).addTile("night");
}
@Test
@@ -398,19 +398,19 @@ public class AutoTileManagerTest extends SysuiTestCase {
}
mAutoTileManager.mNightDisplayCallback.onAutoModeChanged(
ColorDisplayManager.AUTO_MODE_DISABLED);
- verify(mQsTileHost, never()).addTile("night");
+ verify(mQsHost, never()).addTile("night");
}
@Test
public void reduceBrightColorsTileAdded_whenActivated() {
mAutoTileManager.mReduceBrightColorsCallback.onActivated(true);
- verify(mQsTileHost).addTile("reduce_brightness");
+ verify(mQsHost).addTile("reduce_brightness");
}
@Test
public void reduceBrightColorsTileNotAdded_whenDeactivated() {
mAutoTileManager.mReduceBrightColorsCallback.onActivated(false);
- verify(mQsTileHost, never()).addTile("reduce_brightness");
+ verify(mQsHost, never()).addTile("reduce_brightness");
}
private static List<CastDevice> buildFakeCastDevice(boolean isCasting) {
@@ -423,28 +423,28 @@ public class AutoTileManagerTest extends SysuiTestCase {
public void castTileAdded_whenDeviceIsCasting() {
doReturn(buildFakeCastDevice(true)).when(mCastController).getCastDevices();
mAutoTileManager.mCastCallback.onCastDevicesChanged();
- verify(mQsTileHost).addTile("cast");
+ verify(mQsHost).addTile("cast");
}
@Test
public void castTileNotAdded_whenDeviceIsNotCasting() {
doReturn(buildFakeCastDevice(false)).when(mCastController).getCastDevices();
mAutoTileManager.mCastCallback.onCastDevicesChanged();
- verify(mQsTileHost, never()).addTile("cast");
+ verify(mQsHost, never()).addTile("cast");
}
@Test
public void testSettingTileAdded_onChanged() {
changeValue(TEST_SETTING, 1);
verify(mAutoAddTracker).setTileAdded(TEST_SPEC);
- verify(mQsTileHost).addTile(TEST_SPEC);
+ verify(mQsHost).addTile(TEST_SPEC);
}
@Test
public void testSettingTileAddedComponentAtEnd_onChanged() {
changeValue(TEST_SETTING_COMPONENT, 1);
verify(mAutoAddTracker).setTileAdded(TEST_CUSTOM_SPEC);
- verify(mQsTileHost).addTile(ComponentName.unflattenFromString(TEST_COMPONENT)
+ verify(mQsHost).addTile(ComponentName.unflattenFromString(TEST_COMPONENT)
, /* end */ true);
}
@@ -453,14 +453,14 @@ public class AutoTileManagerTest extends SysuiTestCase {
changeValue(TEST_SETTING, 1);
changeValue(TEST_SETTING, 2);
verify(mAutoAddTracker).setTileAdded(TEST_SPEC);
- verify(mQsTileHost).addTile(TEST_SPEC);
+ verify(mQsHost).addTile(TEST_SPEC);
}
@Test
public void testSettingTileNotAdded_onChangedTo0() {
changeValue(TEST_SETTING, 0);
verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC);
- verify(mQsTileHost, never()).addTile(TEST_SPEC);
+ verify(mQsHost, never()).addTile(TEST_SPEC);
}
@Test
@@ -469,27 +469,27 @@ public class AutoTileManagerTest extends SysuiTestCase {
changeValue(TEST_SETTING, 1);
verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC);
- verify(mQsTileHost, never()).addTile(TEST_SPEC);
+ verify(mQsHost, never()).addTile(TEST_SPEC);
}
@Test
public void testSafetyTileNotAdded_ifPreviouslyAdded() {
ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC);
mAutoTileManager.init();
- verify(mQsTileHost, times(1)).addTile(safetyComponent, true);
+ verify(mQsHost, times(1)).addTile(safetyComponent, true);
when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(true);
mAutoTileManager.init();
- verify(mQsTileHost, times(1)).addTile(safetyComponent, true);
+ verify(mQsHost, times(1)).addTile(safetyComponent, true);
}
@Test
public void testSafetyTileAdded_onUserChange() {
ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC);
mAutoTileManager.init();
- verify(mQsTileHost, times(1)).addTile(safetyComponent, true);
+ verify(mQsHost, times(1)).addTile(safetyComponent, true);
when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(false);
mAutoTileManager.changeUser(UserHandle.of(USER + 1));
- verify(mQsTileHost, times(2)).addTile(safetyComponent, true);
+ verify(mQsHost, times(2)).addTile(safetyComponent, true);
}
@Test
@@ -498,17 +498,17 @@ public class AutoTileManagerTest extends SysuiTestCase {
mAutoTileManager.init();
when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(true);
mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false);
- verify(mQsTileHost, times(1)).removeTile(TEST_CUSTOM_SAFETY_SPEC);
+ verify(mQsHost, times(1)).removeTile(TEST_CUSTOM_SAFETY_SPEC);
}
@Test
public void testSafetyTileAdded_onSafetyCenterEnable() {
ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC);
mAutoTileManager.init();
- verify(mQsTileHost, times(1)).addTile(safetyComponent, true);
+ verify(mQsHost, times(1)).addTile(safetyComponent, true);
mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false);
mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(true);
- verify(mQsTileHost, times(2)).addTile(safetyComponent, true);
+ verify(mQsHost, times(2)).addTile(safetyComponent, true);
}
@Test
@@ -525,7 +525,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
mManagedProfileCallback.onManagedProfileChanged();
- verify(mQsTileHost, times(1)).addTile(eq("work"), eq(2));
+ verify(mQsHost, times(1)).addTile(eq("work"), eq(2));
verify(mAutoAddTracker, times(1)).setTileAdded(eq("work"));
}
@@ -542,7 +542,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
mManagedProfileCallback.onManagedProfileChanged();
- verify(mQsTileHost, times(1)).removeTile(eq("work"));
+ verify(mQsHost, times(1)).removeTile(eq("work"));
verify(mAutoAddTracker, times(1)).setTileRemoved(eq("work"));
}
@@ -550,7 +550,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
public void testAddControlsTileIfNotPresent() {
String spec = DEVICE_CONTROLS;
when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(false);
- when(mQsTileHost.getTiles()).thenReturn(new ArrayList<>());
+ when(mQsHost.getTiles()).thenReturn(new ArrayList<>());
mAutoTileManager.init();
ArgumentCaptor<DeviceControlsController.Callback> captor =
@@ -559,7 +559,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
verify(mDeviceControlsController).setCallback(captor.capture());
captor.getValue().onControlsUpdate(3);
- verify(mQsTileHost).addTile(spec, 3);
+ verify(mQsHost).addTile(spec, 3);
verify(mAutoAddTracker).setTileAdded(spec);
}
@@ -567,7 +567,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
public void testDontAddControlsTileIfPresent() {
String spec = DEVICE_CONTROLS;
when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(false);
- when(mQsTileHost.getTiles()).thenReturn(new ArrayList<>());
+ when(mQsHost.getTiles()).thenReturn(new ArrayList<>());
mAutoTileManager.init();
ArgumentCaptor<DeviceControlsController.Callback> captor =
@@ -576,7 +576,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
verify(mDeviceControlsController).setCallback(captor.capture());
captor.getValue().removeControlsAutoTracker();
- verify(mQsTileHost, never()).addTile(spec, 3);
+ verify(mQsHost, never()).addTile(spec, 3);
verify(mAutoAddTracker, never()).setTileAdded(spec);
verify(mAutoAddTracker).setTileRemoved(spec);
}
@@ -587,7 +587,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(true);
QSTile mockTile = mock(QSTile.class);
when(mockTile.getTileSpec()).thenReturn(spec);
- when(mQsTileHost.getTiles()).thenReturn(List.of(mockTile));
+ when(mQsHost.getTiles()).thenReturn(List.of(mockTile));
mAutoTileManager.init();
ArgumentCaptor<DeviceControlsController.Callback> captor =
@@ -596,7 +596,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
verify(mDeviceControlsController).setCallback(captor.capture());
captor.getValue().onControlsUpdate(3);
- verify(mQsTileHost, never()).addTile(spec, 3);
+ verify(mQsHost, never()).addTile(spec, 3);
verify(mAutoAddTracker, never()).setTileAdded(spec);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index daf7dd06b0d2..97226e4e68dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -537,6 +537,26 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
verify(mVibratorHelper).vibrateAuthError(anyString());
}
+ @Test
+ public void onFingerprintDetect_showBouncer() {
+ // WHEN fingerprint detect occurs
+ mBiometricUnlockController.onBiometricDetected(UserHandle.USER_CURRENT,
+ BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */);
+
+ // THEN shows primary bouncer
+ verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
+ }
+
+ @Test
+ public void onFaceDetect_showBouncer() {
+ // WHEN face detect occurs
+ mBiometricUnlockController.onBiometricDetected(UserHandle.USER_CURRENT,
+ BiometricSourceType.FACE, false /* isStrongBiometric */);
+
+ // THEN shows primary bouncer
+ verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
+ }
+
private void givenFingerprintModeUnlockCollapsing() {
when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
index 48573c63d728..2e6f62c2314e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
@@ -43,6 +43,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.CameraLauncher;
import com.android.systemui.shade.NotificationPanelViewController;
@@ -94,6 +95,7 @@ public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase {
@Mock private SystemBarAttributesListener mSystemBarAttributesListener;
@Mock private Lazy<CameraLauncher> mCameraLauncherLazy;
@Mock private UserTracker mUserTracker;
+ @Mock private QSHost mQSHost;
CentralSurfacesCommandQueueCallbacks mSbcqCallbacks;
@@ -128,7 +130,8 @@ public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase {
DEFAULT_DISPLAY,
mSystemBarAttributesListener,
mCameraLauncherLazy,
- mUserTracker);
+ mUserTracker,
+ mQSHost);
when(mUserTracker.getUserHandle()).thenReturn(
UserHandle.of(ActivityManager.getCurrentUser()));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index dbf416e9d1aa..98f5a10aa203 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -1025,6 +1025,45 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
}
@Test
+ public void testSetDozingNotUnlocking_transitionToAuthScrimmed_cancelKeyguardFadingAway() {
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+ when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(true);
+
+ mCentralSurfaces.updateScrimController();
+
+ verify(mScrimController).transitionTo(eq(ScrimState.AUTH_SCRIMMED_SHADE));
+ verify(mStatusBarKeyguardViewManager).onKeyguardFadedAway();
+ }
+
+ @Test
+ public void testOccludingQSNotExpanded_transitionToAuthScrimmed() {
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+
+ // GIVEN device occluded and panel is NOT expanded
+ mCentralSurfaces.setBarStateForTest(SHADE); // occluding on LS has StatusBarState = SHADE
+ when(mKeyguardStateController.isOccluded()).thenReturn(true);
+ mCentralSurfaces.mPanelExpanded = false;
+
+ mCentralSurfaces.updateScrimController();
+
+ verify(mScrimController).transitionTo(eq(ScrimState.AUTH_SCRIMMED));
+ }
+
+ @Test
+ public void testOccludingQSExpanded_transitionToAuthScrimmedShade() {
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+
+ // GIVEN device occluded and qs IS expanded
+ mCentralSurfaces.setBarStateForTest(SHADE); // occluding on LS has StatusBarState = SHADE
+ when(mKeyguardStateController.isOccluded()).thenReturn(true);
+ mCentralSurfaces.mPanelExpanded = true;
+
+ mCentralSurfaces.updateScrimController();
+
+ verify(mScrimController).transitionTo(eq(ScrimState.AUTH_SCRIMMED_SHADE));
+ }
+
+ @Test
public void testShowKeyguardImplementation_setsState() {
when(mLockscreenUserManager.getCurrentProfiles()).thenReturn(new SparseArray<>());
@@ -1248,6 +1287,15 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
verify(mPowerManagerService, never()).wakeUp(anyLong(), anyInt(), anyString(), anyString());
}
+ @Test
+ public void frpLockedDevice_shadeDisabled() {
+ when(mDeviceProvisionedController.isFrpActive()).thenReturn(true);
+ when(mDozeServiceHost.isPulsing()).thenReturn(true);
+ mCentralSurfaces.updateNotificationPanelTouchState();
+
+ verify(mNotificationPanelViewController).setTouchAndAnimationDisabled(true);
+ }
+
/**
* Configures the appropriate mocks and then calls {@link CentralSurfacesImpl#updateIsKeyguard}
* to reconfigure the keyguard to reflect the requested showing/occluded states.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
index eb5edbc21d89..f5b7ca804fbc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
@@ -180,6 +180,7 @@ public class DozeParametersTest extends SysuiTestCase {
when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
mDozeParameters.onTuningChanged(Settings.Secure.DOZE_ALWAYS_ON, "1");
+ verify(mScreenOffAnimationController).onAlwaysOnChanged(false);
assertThat(mDozeParameters.getAlwaysOn()).isFalse();
}
@@ -196,13 +197,16 @@ public class DozeParametersTest extends SysuiTestCase {
mBatteryStateChangeCallback.getValue().onPowerSaveChanged(true);
verify(callback, times(2)).onAlwaysOnChange();
+ verify(mScreenOffAnimationController, times(2)).onAlwaysOnChanged(false);
assertThat(mDozeParameters.getAlwaysOn()).isFalse();
+ reset(mScreenOffAnimationController);
reset(callback);
when(mBatteryController.isAodPowerSave()).thenReturn(false);
mBatteryStateChangeCallback.getValue().onPowerSaveChanged(true);
verify(callback).onAlwaysOnChange();
+ verify(mScreenOffAnimationController).onAlwaysOnChanged(true);
assertThat(mDozeParameters.getAlwaysOn()).isTrue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
index 305b9fea7569..6b18169bcd86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone
import android.app.AlarmManager
-import android.app.IActivityManager
import android.app.admin.DevicePolicyManager
import android.content.SharedPreferences
import android.os.UserManager
@@ -87,7 +86,6 @@ class PhoneStatusBarPolicyTest : SysuiTestCase() {
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var locationController: LocationController
@Mock private lateinit var sensorPrivacyController: SensorPrivacyController
- @Mock private lateinit var iActivityManager: IActivityManager
@Mock private lateinit var alarmManager: AlarmManager
@Mock private lateinit var userManager: UserManager
@Mock private lateinit var userTracker: UserTracker
@@ -176,6 +174,7 @@ class PhoneStatusBarPolicyTest : SysuiTestCase() {
commandQueue,
broadcastDispatcher,
executor,
+ executor,
testableLooper.looper,
context.resources,
castController,
@@ -190,7 +189,6 @@ class PhoneStatusBarPolicyTest : SysuiTestCase() {
keyguardStateController,
locationController,
sensorPrivacyController,
- iActivityManager,
alarmManager,
userManager,
userTracker,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 14d239ab48cd..cdc989897c8e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.phone
import android.view.LayoutInflater
import android.view.MotionEvent
-import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.view.ViewTreeObserver.OnPreDrawListener
import android.widget.FrameLayout
@@ -55,8 +54,6 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@Mock
private lateinit var notificationPanelViewController: NotificationPanelViewController
@Mock
- private lateinit var panelView: ViewGroup
- @Mock
private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
@Mock
private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent
@@ -116,7 +113,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
val returnVal = view.onTouchEvent(
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
assertThat(returnVal).isFalse()
- verify(notificationPanelViewController, never()).sendTouchEventToView(any())
+ verify(notificationPanelViewController, never()).handleExternalTouch(any())
}
@Test
@@ -128,7 +125,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
val returnVal = view.onTouchEvent(
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
assertThat(returnVal).isTrue()
- verify(notificationPanelViewController, never()).sendTouchEventToView(any())
+ verify(notificationPanelViewController, never()).handleExternalTouch(any())
}
@Test
@@ -141,7 +138,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
view.onTouchEvent(event)
- verify(notificationPanelViewController).sendTouchEventToView(event)
+ verify(notificationPanelViewController).handleExternalTouch(event)
}
@Test
@@ -154,7 +151,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
view.onTouchEvent(event)
- verify(notificationPanelViewController).sendTouchEventToView(event)
+ verify(notificationPanelViewController).handleExternalTouch(event)
}
@Test
@@ -167,7 +164,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
view.onTouchEvent(event)
- verify(notificationPanelViewController, never()).sendTouchEventToView(any())
+ verify(notificationPanelViewController, never()).handleExternalTouch(any())
}
private fun createViewMock(): PhoneStatusBarView {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
index 27b1da0cb896..3ed454fff584 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone
import android.view.MotionEvent
import android.view.ViewGroup
import androidx.test.filters.SmallTest
+import com.android.systemui.Gefingerpoken
import com.android.systemui.SysuiTestCase
import com.android.systemui.shade.NotificationPanelViewController
import com.google.common.truth.Truth.assertThat
@@ -94,16 +95,17 @@ class PhoneStatusBarViewTest : SysuiTestCase() {
// No assert needed, just testing no crash
}
- private class TestTouchEventHandler : PhoneStatusBarView.TouchEventHandler {
+ private class TestTouchEventHandler : Gefingerpoken {
var lastInterceptEvent: MotionEvent? = null
var lastEvent: MotionEvent? = null
var handleTouchReturnValue: Boolean = false
- override fun onInterceptTouchEvent(event: MotionEvent?) {
+ override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
lastInterceptEvent = event
+ return handleTouchReturnValue
}
- override fun handleTouchEvent(event: MotionEvent?): Boolean {
+ override fun onTouchEvent(event: MotionEvent?): Boolean {
lastEvent = event
return handleTouchReturnValue
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index c0537a6dc4cf..7a1270f3521d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -39,6 +39,8 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
import android.animation.Animator;
import android.app.AlarmManager;
import android.graphics.Color;
@@ -57,9 +59,18 @@ import com.android.systemui.DejankUtils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
+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.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
import com.android.systemui.scrim.ScrimView;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
+import com.android.systemui.shade.transition.LinearLargeScreenShadeInterpolator;
import com.android.systemui.statusbar.policy.FakeConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -85,8 +96,10 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import kotlinx.coroutines.CoroutineDispatcher;
+
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
public class ScrimControllerTest extends SysuiTestCase {
@@ -94,6 +107,8 @@ public class ScrimControllerTest extends SysuiTestCase {
private final FakeConfigurationController mConfigurationController =
new FakeConfigurationController();
+ private final LargeScreenShadeInterpolator
+ mLinearLargeScreenShadeInterpolator = new LinearLargeScreenShadeInterpolator();
private ScrimController mScrimController;
private ScrimView mScrimBehind;
@@ -115,9 +130,14 @@ public class ScrimControllerTest extends SysuiTestCase {
@Mock private DockManager mDockManager;
@Mock private ScreenOffAnimationController mScreenOffAnimationController;
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+ @Mock private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
+ @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+ @Mock private CoroutineDispatcher mMainDispatcher;
+
// TODO(b/204991468): Use a real PanelExpansionStateManager object once this bug is fixed. (The
// event-dispatch-on-registration pattern caused some of these unit tests to fail.)
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ @Mock private FeatureFlags mFeatureFlags;
private static class AnimatorListener implements Animator.AnimatorListener {
private int mNumStarts;
@@ -225,13 +245,30 @@ public class ScrimControllerTest extends SysuiTestCase {
when(mDelayedWakeLockBuilder.build()).thenReturn(mWakeLock);
when(mDockManager.isDocked()).thenReturn(false);
- mScrimController = new ScrimController(mLightBarController,
- mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
- new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
- mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
+ when(mKeyguardTransitionInteractor.getPrimaryBouncerToGoneTransition())
+ .thenReturn(emptyFlow());
+ when(mPrimaryBouncerToGoneTransitionViewModel.getScrimAlpha())
+ .thenReturn(emptyFlow());
+
+ mScrimController = new ScrimController(
+ mLightBarController,
+ mDozeParameters,
+ mAlarmManager,
+ mKeyguardStateController,
+ mDelayedWakeLockBuilder,
+ new FakeHandler(mLooper.getLooper()),
+ mKeyguardUpdateMonitor,
+ mDockManager,
+ mConfigurationController,
+ new FakeExecutor(new FakeSystemClock()),
mScreenOffAnimationController,
mKeyguardUnlockAnimationController,
- mStatusBarKeyguardViewManager);
+ mStatusBarKeyguardViewManager,
+ mPrimaryBouncerToGoneTransitionViewModel,
+ mKeyguardTransitionInteractor,
+ mMainDispatcher,
+ mLinearLargeScreenShadeInterpolator,
+ mFeatureFlags);
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
mScrimController.setAnimatorListener(mAnimatorListener);
@@ -629,7 +666,81 @@ public class ScrimControllerTest extends SysuiTestCase {
}
@Test
- public void transitionToUnlocked() {
+ public void transitionToUnlocked_clippedQs() {
+ mScrimController.setClipsQsScrim(true);
+ mScrimController.setRawPanelExpansionFraction(0f);
+ mScrimController.transitionTo(ScrimState.UNLOCKED);
+ finishAnimationsImmediately();
+
+ assertScrimTinted(Map.of(
+ mNotificationsScrim, false,
+ mScrimInFront, false,
+ mScrimBehind, true
+ ));
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, TRANSPARENT,
+ mScrimBehind, OPAQUE));
+
+ mScrimController.setRawPanelExpansionFraction(0.25f);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, SEMI_TRANSPARENT,
+ mScrimBehind, OPAQUE));
+
+ mScrimController.setRawPanelExpansionFraction(0.5f);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, OPAQUE,
+ mScrimBehind, OPAQUE));
+ }
+
+ @Test
+ public void transitionToUnlocked_nonClippedQs_flagTrue_followsLargeScreensInterpolator() {
+ when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+ .thenReturn(true);
+ mScrimController.setClipsQsScrim(false);
+ mScrimController.setRawPanelExpansionFraction(0f);
+ mScrimController.transitionTo(ScrimState.UNLOCKED);
+ finishAnimationsImmediately();
+
+ assertScrimTinted(Map.of(
+ mNotificationsScrim, false,
+ mScrimInFront, false,
+ mScrimBehind, true
+ ));
+ // The large screens interpolator used in this test is a linear one, just for tests.
+ // Assertions below are based on this assumption, and that the code uses that interpolator
+ // when on a large screen (QS not clipped).
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, TRANSPARENT,
+ mScrimBehind, TRANSPARENT));
+
+ mScrimController.setRawPanelExpansionFraction(0.5f);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, SEMI_TRANSPARENT,
+ mScrimBehind, SEMI_TRANSPARENT));
+
+ mScrimController.setRawPanelExpansionFraction(0.99f);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, SEMI_TRANSPARENT,
+ mScrimBehind, SEMI_TRANSPARENT));
+
+ mScrimController.setRawPanelExpansionFraction(1f);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, OPAQUE,
+ mScrimBehind, OPAQUE));
+ }
+
+
+ @Test
+ public void transitionToUnlocked_nonClippedQs_flagFalse() {
+ when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+ .thenReturn(false);
mScrimController.setClipsQsScrim(false);
mScrimController.setRawPanelExpansionFraction(0f);
mScrimController.transitionTo(ScrimState.UNLOCKED);
@@ -667,7 +778,6 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimBehind, OPAQUE));
}
-
@Test
public void scrimStateCallback() {
mScrimController.transitionTo(ScrimState.UNLOCKED);
@@ -855,13 +965,25 @@ public class ScrimControllerTest extends SysuiTestCase {
// GIVEN display does NOT need blanking
when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(false);
- mScrimController = new ScrimController(mLightBarController,
- mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
- new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
- mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
+ mScrimController = new ScrimController(
+ mLightBarController,
+ mDozeParameters,
+ mAlarmManager,
+ mKeyguardStateController,
+ mDelayedWakeLockBuilder,
+ new FakeHandler(mLooper.getLooper()),
+ mKeyguardUpdateMonitor,
+ mDockManager,
+ mConfigurationController,
+ new FakeExecutor(new FakeSystemClock()),
mScreenOffAnimationController,
mKeyguardUnlockAnimationController,
- mStatusBarKeyguardViewManager);
+ mStatusBarKeyguardViewManager,
+ mPrimaryBouncerToGoneTransitionViewModel,
+ mKeyguardTransitionInteractor,
+ mMainDispatcher,
+ mLinearLargeScreenShadeInterpolator,
+ mFeatureFlags);
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
mScrimController.setAnimatorListener(mAnimatorListener);
@@ -1356,33 +1478,10 @@ public class ScrimControllerTest extends SysuiTestCase {
}
@Test
- public void notificationAlpha_unnocclusionAnimating_bouncerActive_usesKeyguardNotifAlpha() {
- when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(true);
- mScrimController.setClipsQsScrim(true);
-
- mScrimController.transitionTo(ScrimState.KEYGUARD);
- mScrimController.setUnocclusionAnimationRunning(true);
-
- assertAlphaAfterExpansion(
- mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0f);
- assertAlphaAfterExpansion(
- mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0.4f);
- assertAlphaAfterExpansion(
- mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 1.0f);
-
- // Verify normal behavior after
- mScrimController.setUnocclusionAnimationRunning(false);
- float expansion = 0.4f;
- float alpha = 1 - BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion);
- assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion);
- }
-
- @Test
public void notificationAlpha_unnocclusionAnimating_bouncerNotActive_usesKeyguardNotifAlpha() {
when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false);
mScrimController.transitionTo(ScrimState.KEYGUARD);
- mScrimController.setUnocclusionAnimationRunning(true);
assertAlphaAfterExpansion(
mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0f);
@@ -1392,7 +1491,6 @@ public class ScrimControllerTest extends SysuiTestCase {
mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 1.0f);
// Verify normal behavior after
- mScrimController.setUnocclusionAnimationRunning(false);
float expansion = 0.4f;
float alpha = 1 - ShadeInterpolation.getNotificationScrimAlpha(expansion);
assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion);
@@ -1598,7 +1696,6 @@ public class ScrimControllerTest extends SysuiTestCase {
@Test
public void setUnOccludingAnimationKeyguard() {
- mScrimController.setUnocclusionAnimationRunning(true);
mScrimController.transitionTo(ScrimState.KEYGUARD);
finishAnimationsImmediately();
assertThat(mNotificationsScrim.getViewAlpha())
@@ -1654,6 +1751,28 @@ public class ScrimControllerTest extends SysuiTestCase {
assertScrimAlpha(mScrimBehind, 0);
}
+ @Test
+ public void ignoreTransitionRequestWhileKeyguardTransitionRunning() {
+ mScrimController.transitionTo(ScrimState.UNLOCKED);
+ mScrimController.mPrimaryBouncerToGoneTransition.accept(
+ new TransitionStep(KeyguardState.PRIMARY_BOUNCER, KeyguardState.GONE, 0f,
+ TransitionState.RUNNING, "ScrimControllerTest"));
+
+ // This request should not happen
+ mScrimController.transitionTo(ScrimState.BOUNCER);
+ assertThat(mScrimController.getState()).isEqualTo(ScrimState.UNLOCKED);
+ }
+
+ @Test
+ public void primaryBouncerToGoneOnFinishCallsKeyguardFadedAway() {
+ when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(true);
+ mScrimController.mPrimaryBouncerToGoneTransition.accept(
+ new TransitionStep(KeyguardState.PRIMARY_BOUNCER, KeyguardState.GONE, 0f,
+ TransitionState.FINISHED, "ScrimControllerTest"));
+
+ verify(mStatusBarKeyguardViewManager).onKeyguardFadedAway();
+ }
+
private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
mScrimController.setRawPanelExpansionFraction(expansion);
finishAnimationsImmediately();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index d8446f4721b3..31462623ce2d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone;
import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -35,9 +36,12 @@ import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
+import android.view.WindowInsets;
+import android.view.WindowInsetsController;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedCallback;
@@ -65,8 +69,10 @@ import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInt
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.navigationbar.TaskbarDelegate;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.shade.NotificationPanelViewController;
+import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shade.ShadeExpansionStateManager;
@@ -123,6 +129,9 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Mock private BouncerView mBouncerView;
@Mock private BouncerViewDelegate mBouncerViewDelegate;
@Mock private OnBackAnimationCallback mBouncerViewDelegateBackCallback;
+ @Mock private NotificationShadeWindowView mNotificationShadeWindowView;
+ @Mock private WindowInsetsController mWindowInsetsController;
+ @Mock private TaskbarDelegate mTaskbarDelegate;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback
@@ -151,6 +160,11 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM))
.thenReturn(true);
+ when(mCentralSurfaces.getNotificationShadeWindowView())
+ .thenReturn(mNotificationShadeWindowView);
+ when(mNotificationShadeWindowView.getWindowInsetsController())
+ .thenReturn(mWindowInsetsController);
+
mStatusBarKeyguardViewManager =
new StatusBarKeyguardViewManager(
getContext(),
@@ -356,17 +370,6 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
- public void setOccluded_animatesPanelExpansion_onlyIfBouncerHidden() {
- mStatusBarKeyguardViewManager.setOccluded(false /* occluded */, true /* animated */);
- verify(mCentralSurfaces).animateKeyguardUnoccluding();
-
- when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true);
- clearInvocations(mCentralSurfaces);
- mStatusBarKeyguardViewManager.setOccluded(false /* occluded */, true /* animated */);
- verify(mCentralSurfaces, never()).animateKeyguardUnoccluding();
- }
-
- @Test
public void setOccluded_onKeyguardOccludedChangedCalled() {
clearInvocations(mKeyguardStateController);
clearInvocations(mKeyguardUpdateMonitor);
@@ -640,6 +643,14 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
+ public void testHideTaskbar() {
+ when(mTaskbarDelegate.isInitialized()).thenReturn(true);
+ mStatusBarKeyguardViewManager.setTaskbarDelegate(mTaskbarDelegate);
+ mStatusBarKeyguardViewManager.updateNavigationBarVisibility(false);
+ verify(mWindowInsetsController).hide(WindowInsets.Type.navigationBars());
+ }
+
+ @Test
public void hideAlternateBouncer_beforeCentralSurfacesRegistered() {
mStatusBarKeyguardViewManager =
new StatusBarKeyguardViewManager(
@@ -674,4 +685,74 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
// the following call before registering centralSurfaces should NOT throw a NPE:
mStatusBarKeyguardViewManager.hideAlternateBouncer(true);
}
+
+ @Test
+ public void testResetHideBouncerWhenShowing_alternateBouncerHides() {
+ // GIVEN the keyguard is showing
+ reset(mAlternateBouncerInteractor);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+
+ // WHEN SBKV is reset with hideBouncerWhenShowing=true
+ mStatusBarKeyguardViewManager.reset(true);
+
+ // THEN alternate bouncer is hidden
+ verify(mAlternateBouncerInteractor).hide();
+ }
+
+ @Test
+ public void testResetHideBouncerWhenShowingIsFalse_alternateBouncerHides() {
+ // GIVEN the keyguard is showing
+ reset(mAlternateBouncerInteractor);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+
+ // WHEN SBKV is reset with hideBouncerWhenShowing=false
+ mStatusBarKeyguardViewManager.reset(false);
+
+ // THEN alternate bouncer is NOT hidden
+ verify(mAlternateBouncerInteractor, never()).hide();
+ }
+
+ @Test
+ public void testAlternateBouncerToShowPrimaryBouncer_updatesScrimControllerOnce() {
+ // GIVEN the alternate bouncer has shown and calls to hide() will result in successfully
+ // hiding it
+ when(mAlternateBouncerInteractor.hide()).thenReturn(true);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(false);
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(false);
+
+ // WHEN request to show primary bouncer
+ mStatusBarKeyguardViewManager.showPrimaryBouncer(true);
+
+ // THEN the scrim isn't updated from StatusBarKeyguardViewManager
+ verify(mCentralSurfaces, never()).updateScrimController();
+ }
+
+ @Test
+ public void testAlternateBouncerOnTouch_actionDown_doesNotHandleTouch() {
+ // GIVEN the alternate bouncer has shown for a minimum amount of time
+ when(mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()).thenReturn(true);
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+
+ // WHEN ACTION_DOWN touch event comes
+ boolean touchHandled = mStatusBarKeyguardViewManager.onTouch(
+ MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0));
+
+ // THEN the touch is not handled
+ assertFalse(touchHandled);
+ }
+
+ @Test
+ public void testAlternateBouncerOnTouch_actionUp_handlesTouch() {
+ // GIVEN the alternate bouncer has shown for a minimum amount of time
+ when(mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()).thenReturn(true);
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+
+ // WHEN ACTION_UP touch event comes
+ boolean touchHandled = mStatusBarKeyguardViewManager.onTouch(
+ MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0));
+
+ // THEN the touch is handled
+ assertTrue(touchHandled);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt
index 1779de729e5b..7594c90daa8b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt
@@ -8,13 +8,14 @@ import android.view.WindowManager
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.unfold.TestUnfoldTransitionProvider
+import com.android.systemui.unfold.util.CurrentActivityTypeProvider
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
+import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatchers.any
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@SmallTest
@@ -26,6 +27,9 @@ class StatusBarMoveFromCenterAnimationControllerTest : SysuiTestCase() {
@Mock
private lateinit var display: Display
+ @Mock
+ private lateinit var currentActivityTypeProvider: CurrentActivityTypeProvider
+
private val view: View = View(context)
private val progressProvider = TestUnfoldTransitionProvider()
private val scopedProvider = ScopedUnfoldTransitionProgressProvider(progressProvider)
@@ -36,9 +40,9 @@ class StatusBarMoveFromCenterAnimationControllerTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
- `when`(windowManager.defaultDisplay).thenReturn(display)
- `when`(display.rotation).thenReturn(Surface.ROTATION_0)
- `when`(display.getSize(any())).thenAnswer {
+ whenever(windowManager.defaultDisplay).thenReturn(display)
+ whenever(display.rotation).thenReturn(Surface.ROTATION_0)
+ whenever(display.getSize(any())).thenAnswer {
val point = it.arguments[0] as Point
point.x = 100
point.y = 100
@@ -47,7 +51,12 @@ class StatusBarMoveFromCenterAnimationControllerTest : SysuiTestCase() {
scopedProvider.setReadyToHandleTransition(true)
- controller = StatusBarMoveFromCenterAnimationController(scopedProvider, windowManager)
+ controller =
+ StatusBarMoveFromCenterAnimationController(
+ scopedProvider,
+ currentActivityTypeProvider,
+ windowManager
+ )
}
@Test
@@ -99,6 +108,31 @@ class StatusBarMoveFromCenterAnimationControllerTest : SysuiTestCase() {
}
@Test
+ fun alpha_onLauncher_alphaDoesNotChange() {
+ whenever(currentActivityTypeProvider.isHomeActivity).thenReturn(true)
+ controller.onViewsReady(arrayOf(view))
+ progressProvider.onTransitionStarted()
+ progressProvider.onTransitionProgress(0.0f)
+ assertThat(view.alpha).isEqualTo(1.0f)
+
+ progressProvider.onTransitionProgress(1.0f)
+
+ assertThat(view.alpha).isEqualTo(1.0f)
+ }
+
+ @Test
+ fun alpha_NotOnLauncher_alphaChanges() {
+ whenever(currentActivityTypeProvider.isHomeActivity).thenReturn(false)
+ controller.onViewsReady(arrayOf(view))
+ progressProvider.onTransitionStarted()
+ assertThat(view.alpha).isEqualTo(1.0f)
+
+ progressProvider.onTransitionProgress(0.5f)
+
+ assertThat(view.alpha).isNotEqualTo(1.0f)
+ }
+
+ @Test
fun transitionFinished_viewReAttached_noChangesToTranslation() {
controller.onViewsReady(arrayOf(view))
progressProvider.onTransitionProgress(0.5f)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index ccc57ad72f36..ee7e082c839f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -18,6 +18,9 @@ package com.android.systemui.statusbar.phone;
import static android.service.notification.NotificationListenerService.REASON_CLICK;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
import static org.mockito.AdditionalAnswers.answerVoid;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -28,7 +31,6 @@ import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@@ -38,6 +40,8 @@ import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ResolveInfo;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -51,6 +55,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.SysuiTestCase;
@@ -90,9 +95,12 @@ import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
import org.mockito.stubbing.Answer;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@@ -398,4 +406,40 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
// THEN display should try wake up for the full screen intent
verify(mCentralSurfaces).wakeUpForFullScreenIntent();
}
+
+ @Test
+ public void testOnFullScreenIntentWhenDozing_logToStatsd() {
+ final int kTestUid = 12345;
+ final String kTestActivityName = "TestActivity";
+ // GIVEN entry that can has a full screen intent that can show
+ PendingIntent mockFullScreenIntent = mock(PendingIntent.class);
+ when(mockFullScreenIntent.getCreatorUid()).thenReturn(kTestUid);
+ ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.activityInfo = new ActivityInfo();
+ resolveInfo.activityInfo.name = kTestActivityName;
+ when(mockFullScreenIntent.queryIntentComponents(anyInt()))
+ .thenReturn(Arrays.asList(resolveInfo));
+ Notification.Builder nb = new Notification.Builder(mContext, "a")
+ .setContentTitle("foo")
+ .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .setFullScreenIntent(mockFullScreenIntent, true);
+ StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0,
+ "tag" + System.currentTimeMillis(), 0, 0,
+ nb.build(), new UserHandle(0), null, 0);
+ NotificationEntry entry = mock(NotificationEntry.class);
+ when(entry.getImportance()).thenReturn(NotificationManager.IMPORTANCE_HIGH);
+ when(entry.getSbn()).thenReturn(sbn);
+ MockitoSession mockingSession = mockitoSession()
+ .mockStatic(FrameworkStatsLog.class)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
+
+ // WHEN
+ mNotificationActivityStarter.launchFullScreenIntent(entry);
+
+ // THEN the full screen intent should be logged to statsd.
+ verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.FULL_SCREEN_INTENT_LAUNCHED,
+ kTestUid, kTestActivityName));
+ mockingSession.finishMocking();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index 07e8d3c19518..1e5782b91be8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -32,7 +32,6 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import android.animation.Animator;
import android.app.Fragment;
import android.app.StatusBarManager;
import android.content.Context;
@@ -45,6 +44,7 @@ import android.view.View;
import android.view.ViewPropertyAnimator;
import android.widget.FrameLayout;
+import androidx.core.animation.Animator;
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLoggerTest.kt
index 86529dce948a..7c9351c8495d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLoggerTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.pipeline.mobile.shared
+package com.android.systemui.statusbar.pipeline.mobile.data
import android.net.Network
import android.net.NetworkCapabilities
@@ -47,14 +47,14 @@ class MobileInputLoggerTest : SysuiTestCase() {
val expectedNetId = NET_1_ID.toString()
val expectedCaps = NET_1_CAPS.toString()
- assertThat(actualString).contains("true")
+ assertThat(actualString).contains("onDefaultCapabilitiesChanged")
assertThat(actualString).contains(expectedNetId)
assertThat(actualString).contains(expectedCaps)
}
@Test
fun testLogOnLost_bufferHasNetIdOfLostNetwork() {
- logger.logOnLost(NET_1)
+ logger.logOnLost(NET_1, isDefaultNetworkCallback = false)
val stringWriter = StringWriter()
buffer.dump(PrintWriter(stringWriter), tailLength = 0)
@@ -62,6 +62,7 @@ class MobileInputLoggerTest : SysuiTestCase() {
val expectedNetId = NET_1_ID.toString()
+ assertThat(actualString).contains("onLost")
assertThat(actualString).contains(expectedNetId)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt
deleted file mode 100644
index 45189cf8d432..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt
+++ /dev/null
@@ -1,106 +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.systemui.statusbar.pipeline.mobile.data.model
-
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.log.table.TableRowLogger
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION_IN
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION_OUT
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CARRIER_NETWORK_CHANGE
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CDMA_LEVEL
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CONNECTION_STATE
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_EMERGENCY
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_IS_GSM
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_OPERATOR
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_PRIMARY_LEVEL
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_RESOLVED_NETWORK_TYPE
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ROAMING
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-
-@SmallTest
-class MobileConnectionModelTest : SysuiTestCase() {
-
- @Test
- fun `log diff - initial log contains all columns`() {
- val logger = TestLogger()
- val connection = MobileConnectionModel()
-
- connection.logFull(logger)
-
- assertThat(logger.changes)
- .contains(Pair(COL_EMERGENCY, connection.isEmergencyOnly.toString()))
- assertThat(logger.changes).contains(Pair(COL_ROAMING, connection.isRoaming.toString()))
- assertThat(logger.changes)
- .contains(Pair(COL_OPERATOR, connection.operatorAlphaShort.toString()))
- assertThat(logger.changes).contains(Pair(COL_IS_GSM, connection.isGsm.toString()))
- assertThat(logger.changes).contains(Pair(COL_CDMA_LEVEL, connection.cdmaLevel.toString()))
- assertThat(logger.changes)
- .contains(Pair(COL_PRIMARY_LEVEL, connection.primaryLevel.toString()))
- assertThat(logger.changes)
- .contains(Pair(COL_CONNECTION_STATE, connection.dataConnectionState.toString()))
- assertThat(logger.changes)
- .contains(
- Pair(
- COL_ACTIVITY_DIRECTION_IN,
- connection.dataActivityDirection.hasActivityIn.toString(),
- )
- )
- assertThat(logger.changes)
- .contains(
- Pair(
- COL_ACTIVITY_DIRECTION_OUT,
- connection.dataActivityDirection.hasActivityOut.toString(),
- )
- )
- assertThat(logger.changes)
- .contains(
- Pair(COL_CARRIER_NETWORK_CHANGE, connection.carrierNetworkChangeActive.toString())
- )
- assertThat(logger.changes)
- .contains(Pair(COL_RESOLVED_NETWORK_TYPE, connection.resolvedNetworkType.toString()))
- }
-
- @Test
- fun `log diff - primary level changes - only level is logged`() {
- val logger = TestLogger()
- val connectionOld = MobileConnectionModel(primaryLevel = 1)
-
- val connectionNew = MobileConnectionModel(primaryLevel = 2)
-
- connectionNew.logDiffs(connectionOld, logger)
-
- assertThat(logger.changes).isEqualTo(listOf(Pair(COL_PRIMARY_LEVEL, "2")))
- }
-
- private class TestLogger : TableRowLogger {
- val changes = mutableListOf<Pair<String, String>>()
-
- override fun logChange(columnName: String, value: String?) {
- changes.add(Pair(columnName, value.toString()))
- }
-
- override fun logChange(columnName: String, value: Int) {
- changes.add(Pair(columnName, value.toString()))
- }
-
- override fun logChange(columnName: String, value: Boolean) {
- changes.add(Pair(columnName, value.toString()))
- }
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
index 0145103d55e1..dfef62e95eda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
@@ -24,8 +24,8 @@ import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
index 53cd71f1bdf9..44fbd5b99894 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
@@ -17,9 +17,11 @@
package com.android.systemui.statusbar.pipeline.mobile.data.repository
import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import kotlinx.coroutines.flow.MutableStateFlow
// TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionRepository
@@ -27,8 +29,19 @@ class FakeMobileConnectionRepository(
override val subId: Int,
override val tableLogBuffer: TableLogBuffer,
) : MobileConnectionRepository {
- private val _connectionInfo = MutableStateFlow(MobileConnectionModel())
- override val connectionInfo = _connectionInfo
+ override val isEmergencyOnly = MutableStateFlow(false)
+ override val isRoaming = MutableStateFlow(false)
+ override val operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null)
+ override val isInService = MutableStateFlow(false)
+ override val isGsm = MutableStateFlow(false)
+ override val cdmaLevel = MutableStateFlow(0)
+ override val primaryLevel = MutableStateFlow(0)
+ override val dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected)
+ override val dataActivityDirection =
+ MutableStateFlow(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
+ override val carrierNetworkChangeActive = MutableStateFlow(false)
+ override val resolvedNetworkType: MutableStateFlow<ResolvedNetworkType> =
+ MutableStateFlow(ResolvedNetworkType.UnknownNetworkType)
override val numberOfLevels = MutableStateFlow(DEFAULT_NUM_LEVELS)
@@ -40,10 +53,6 @@ class FakeMobileConnectionRepository(
override val networkName =
MutableStateFlow<NetworkNameModel>(NetworkNameModel.Default("default"))
- fun setConnectionInfo(model: MobileConnectionModel) {
- _connectionInfo.value = model
- }
-
fun setDataEnabled(enabled: Boolean) {
_dataEnabled.value = enabled
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
index 17502f28a479..07c8cee9a3d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
@@ -27,13 +27,13 @@ import com.android.systemui.demomode.DemoModeController
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoModeMobileConnectionDataSource
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.validMobileEvent
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileConnectionsRepositoryImpl
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
index 00ce412f2a65..37fac3458c83 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
@@ -25,7 +25,6 @@ import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
@@ -36,8 +35,11 @@ import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
@@ -123,34 +125,49 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
assertConnection(underTest, networkModel)
}
- private fun assertConnection(
+ private fun TestScope.startCollection(conn: DemoMobileConnectionRepository): Job {
+ val job = launch {
+ launch { conn.cdmaLevel.collect {} }
+ launch { conn.primaryLevel.collect {} }
+ launch { conn.dataActivityDirection.collect {} }
+ launch { conn.carrierNetworkChangeActive.collect {} }
+ launch { conn.isRoaming.collect {} }
+ launch { conn.networkName.collect {} }
+ launch { conn.isEmergencyOnly.collect {} }
+ launch { conn.dataConnectionState.collect {} }
+ }
+ return job
+ }
+
+ private fun TestScope.assertConnection(
conn: DemoMobileConnectionRepository,
model: FakeNetworkEventModel
) {
+ val job = startCollection(underTest)
when (model) {
is FakeNetworkEventModel.Mobile -> {
- val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
assertThat(conn.subId).isEqualTo(model.subId)
- assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
- assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
- assertThat(connectionInfo.dataActivityDirection)
+ assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
+ assertThat(conn.primaryLevel.value).isEqualTo(model.level)
+ assertThat(conn.dataActivityDirection.value)
.isEqualTo((model.activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel())
- assertThat(connectionInfo.carrierNetworkChangeActive)
+ assertThat(conn.carrierNetworkChangeActive.value)
.isEqualTo(model.carrierNetworkChange)
- assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming)
+ assertThat(conn.isRoaming.value).isEqualTo(model.roaming)
assertThat(conn.networkName.value)
.isEqualTo(NetworkNameModel.IntentDerived(model.name))
// TODO(b/261029387): check these once we start handling them
- assertThat(connectionInfo.isEmergencyOnly).isFalse()
- assertThat(connectionInfo.isGsm).isFalse()
- assertThat(connectionInfo.dataConnectionState)
- .isEqualTo(DataConnectionState.Connected)
+ assertThat(conn.isEmergencyOnly.value).isFalse()
+ assertThat(conn.isGsm.value).isFalse()
+ assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
}
// MobileDisabled isn't combinatorial in nature, and is tested in
// DemoMobileConnectionsRepositoryTest.kt
else -> {}
}
+
+ job.cancel()
}
/** Matches [FakeNetworkEventModel] */
@@ -239,6 +256,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
* list2 = [false, true]
* list3 = [a, b, c]
* ```
+ *
* We'll generate test cases for:
*
* Test (1, false, a) Test (2, false, a) Test (3, false, a) Test (1, true, a) Test (1,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
index f60d92bde202..0e45d8ea5563 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
@@ -26,7 +26,6 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
@@ -40,9 +39,11 @@ import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
@@ -524,47 +525,65 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
job.cancel()
}
- private fun assertConnection(
+ private fun TestScope.startCollection(conn: DemoMobileConnectionRepository): Job {
+ val job = launch {
+ launch { conn.cdmaLevel.collect {} }
+ launch { conn.primaryLevel.collect {} }
+ launch { conn.dataActivityDirection.collect {} }
+ launch { conn.carrierNetworkChangeActive.collect {} }
+ launch { conn.isRoaming.collect {} }
+ launch { conn.networkName.collect {} }
+ launch { conn.isEmergencyOnly.collect {} }
+ launch { conn.dataConnectionState.collect {} }
+ }
+ return job
+ }
+
+ private fun TestScope.assertConnection(
conn: DemoMobileConnectionRepository,
- model: FakeNetworkEventModel
+ model: FakeNetworkEventModel,
) {
+ val job = startCollection(conn)
+ // Assert the fields using the `MutableStateFlow` so that we don't have to start up
+ // a collector for every field for every test
when (model) {
is FakeNetworkEventModel.Mobile -> {
- val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
assertThat(conn.subId).isEqualTo(model.subId)
- assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
- assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
- assertThat(connectionInfo.dataActivityDirection)
+ assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
+ assertThat(conn.primaryLevel.value).isEqualTo(model.level)
+ assertThat(conn.dataActivityDirection.value)
.isEqualTo((model.activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel())
- assertThat(connectionInfo.carrierNetworkChangeActive)
+ assertThat(conn.carrierNetworkChangeActive.value)
.isEqualTo(model.carrierNetworkChange)
- assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming)
+ assertThat(conn.isRoaming.value).isEqualTo(model.roaming)
assertThat(conn.networkName.value)
.isEqualTo(NetworkNameModel.IntentDerived(model.name))
// TODO(b/261029387) check these once we start handling them
- assertThat(connectionInfo.isEmergencyOnly).isFalse()
- assertThat(connectionInfo.isGsm).isFalse()
- assertThat(connectionInfo.dataConnectionState)
- .isEqualTo(DataConnectionState.Connected)
+ assertThat(conn.isEmergencyOnly.value).isFalse()
+ assertThat(conn.isGsm.value).isFalse()
+ assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
}
else -> {}
}
+
+ job.cancel()
}
- private fun assertCarrierMergedConnection(
+ private fun TestScope.assertCarrierMergedConnection(
conn: DemoMobileConnectionRepository,
model: FakeWifiEventModel.CarrierMerged,
) {
- val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
+ val job = startCollection(conn)
assertThat(conn.subId).isEqualTo(model.subscriptionId)
- assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
- assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
- assertThat(connectionInfo.carrierNetworkChangeActive).isEqualTo(false)
- assertThat(connectionInfo.isRoaming).isEqualTo(false)
- assertThat(connectionInfo.isEmergencyOnly).isFalse()
- assertThat(connectionInfo.isGsm).isFalse()
- assertThat(connectionInfo.dataConnectionState).isEqualTo(DataConnectionState.Connected)
+ assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
+ assertThat(conn.primaryLevel.value).isEqualTo(model.level)
+ assertThat(conn.carrierNetworkChangeActive.value).isEqualTo(false)
+ assertThat(conn.isRoaming.value).isEqualTo(false)
+ assertThat(conn.isEmergencyOnly.value).isFalse()
+ assertThat(conn.isGsm.value).isFalse()
+ assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
+ job.cancel()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
index f0f213bc0d58..441186acb6b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
@@ -22,7 +22,6 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
@@ -75,36 +74,48 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun connectionInfo_inactiveWifi_isDefault() =
+ fun inactiveWifi_isDefault() =
testScope.runTest {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ var latestConnState: DataConnectionState? = null
+ var latestNetType: ResolvedNetworkType? = null
+
+ val dataJob =
+ underTest.dataConnectionState.onEach { latestConnState = it }.launchIn(this)
+ val netJob = underTest.resolvedNetworkType.onEach { latestNetType = it }.launchIn(this)
wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive)
- assertThat(latest).isEqualTo(MobileConnectionModel())
+ assertThat(latestConnState).isEqualTo(DataConnectionState.Disconnected)
+ assertThat(latestNetType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
- job.cancel()
+ dataJob.cancel()
+ netJob.cancel()
}
@Test
- fun connectionInfo_activeWifi_isDefault() =
+ fun activeWifi_isDefault() =
testScope.runTest {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ var latestConnState: DataConnectionState? = null
+ var latestNetType: ResolvedNetworkType? = null
+
+ val dataJob =
+ underTest.dataConnectionState.onEach { latestConnState = it }.launchIn(this)
+ val netJob = underTest.resolvedNetworkType.onEach { latestNetType = it }.launchIn(this)
wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = NET_ID, level = 1))
- assertThat(latest).isEqualTo(MobileConnectionModel())
+ assertThat(latestConnState).isEqualTo(DataConnectionState.Disconnected)
+ assertThat(latestNetType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
- job.cancel()
+ dataJob.cancel()
+ netJob.cancel()
}
@Test
- fun connectionInfo_carrierMergedWifi_isValidAndFieldsComeFromWifiNetwork() =
+ fun carrierMergedWifi_isValidAndFieldsComeFromWifiNetwork() =
testScope.runTest {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ var latest: Int? = null
+ val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
wifiRepository.setIsWifiEnabled(true)
wifiRepository.setIsWifiDefault(true)
@@ -117,34 +128,16 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
)
)
- val expected =
- MobileConnectionModel(
- primaryLevel = 3,
- cdmaLevel = 3,
- dataConnectionState = DataConnectionState.Connected,
- dataActivityDirection =
- DataActivityModel(
- hasActivityIn = false,
- hasActivityOut = false,
- ),
- resolvedNetworkType = ResolvedNetworkType.CarrierMergedNetworkType,
- isRoaming = false,
- isEmergencyOnly = false,
- operatorAlphaShort = null,
- isInService = true,
- isGsm = false,
- carrierNetworkChangeActive = false,
- )
- assertThat(latest).isEqualTo(expected)
+ assertThat(latest).isEqualTo(3)
job.cancel()
}
@Test
- fun connectionInfo_activity_comesFromWifiActivity() =
+ fun activity_comesFromWifiActivity() =
testScope.runTest {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ var latest: DataActivityModel? = null
+ val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
wifiRepository.setIsWifiEnabled(true)
wifiRepository.setIsWifiDefault(true)
@@ -162,8 +155,8 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
)
)
- assertThat(latest!!.dataActivityDirection.hasActivityIn).isTrue()
- assertThat(latest!!.dataActivityDirection.hasActivityOut).isFalse()
+ assertThat(latest!!.hasActivityIn).isTrue()
+ assertThat(latest!!.hasActivityOut).isFalse()
wifiRepository.setWifiActivity(
DataActivityModel(
@@ -172,17 +165,19 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
)
)
- assertThat(latest!!.dataActivityDirection.hasActivityIn).isFalse()
- assertThat(latest!!.dataActivityDirection.hasActivityOut).isTrue()
+ assertThat(latest!!.hasActivityIn).isFalse()
+ assertThat(latest!!.hasActivityOut).isTrue()
job.cancel()
}
@Test
- fun connectionInfo_carrierMergedWifi_wrongSubId_isDefault() =
+ fun carrierMergedWifi_wrongSubId_isDefault() =
testScope.runTest {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ var latestLevel: Int? = null
+ var latestType: ResolvedNetworkType? = null
+ val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
+ val typeJob = underTest.resolvedNetworkType.onEach { latestType = it }.launchIn(this)
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
@@ -192,20 +187,19 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
)
)
- assertThat(latest).isEqualTo(MobileConnectionModel())
- assertThat(latest!!.primaryLevel).isNotEqualTo(3)
- assertThat(latest!!.resolvedNetworkType)
- .isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
+ assertThat(latestLevel).isNotEqualTo(3)
+ assertThat(latestType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
- job.cancel()
+ levelJob.cancel()
+ typeJob.cancel()
}
// This scenario likely isn't possible, but write a test for it anyway
@Test
- fun connectionInfo_carrierMergedButNotEnabled_isDefault() =
+ fun carrierMergedButNotEnabled_isDefault() =
testScope.runTest {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ var latest: Int? = null
+ val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
@@ -216,17 +210,17 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
)
wifiRepository.setIsWifiEnabled(false)
- assertThat(latest).isEqualTo(MobileConnectionModel())
+ assertThat(latest).isNotEqualTo(3)
job.cancel()
}
// This scenario likely isn't possible, but write a test for it anyway
@Test
- fun connectionInfo_carrierMergedButWifiNotDefault_isDefault() =
+ fun carrierMergedButWifiNotDefault_isDefault() =
testScope.runTest {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ var latest: Int? = null
+ val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
@@ -237,7 +231,7 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
)
wifiRepository.setIsWifiDefault(false)
- assertThat(latest).isEqualTo(MobileConnectionModel())
+ assertThat(latest).isNotEqualTo(3)
job.cancel()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
index cd4d8472763f..db5a7d1ad84a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
@@ -24,13 +24,12 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_EMERGENCY
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_OPERATOR
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_PRIMARY_LEVEL
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_EMERGENCY
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_OPERATOR
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_PRIMARY_LEVEL
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.getTelephonyCallbackForType
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
@@ -94,16 +93,16 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
@Test
fun startingIsCarrierMerged_usesCarrierMergedInitially() =
testScope.runTest {
- val carrierMergedConnectionInfo =
- MobileConnectionModel(
- operatorAlphaShort = "Carrier Merged Operator",
- )
- carrierMergedRepo.setConnectionInfo(carrierMergedConnectionInfo)
+ val carrierMergedOperatorName = "Carrier Merged Operator"
+ val nonCarrierMergedName = "Non-carrier-merged"
+
+ carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperatorName
+ mobileRepo.operatorAlphaShort.value = nonCarrierMergedName
initializeRepo(startingIsCarrierMerged = true)
assertThat(underTest.activeRepo.value).isEqualTo(carrierMergedRepo)
- assertThat(underTest.connectionInfo.value).isEqualTo(carrierMergedConnectionInfo)
+ assertThat(underTest.operatorAlphaShort.value).isEqualTo(carrierMergedOperatorName)
verify(mobileFactory, never())
.build(
SUB_ID,
@@ -116,16 +115,16 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
@Test
fun startingNotCarrierMerged_usesTypicalInitially() =
testScope.runTest {
- val mobileConnectionInfo =
- MobileConnectionModel(
- operatorAlphaShort = "Typical Operator",
- )
- mobileRepo.setConnectionInfo(mobileConnectionInfo)
+ val carrierMergedOperatorName = "Carrier Merged Operator"
+ val nonCarrierMergedName = "Typical Operator"
+
+ carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperatorName
+ mobileRepo.operatorAlphaShort.value = nonCarrierMergedName
initializeRepo(startingIsCarrierMerged = false)
assertThat(underTest.activeRepo.value).isEqualTo(mobileRepo)
- assertThat(underTest.connectionInfo.value).isEqualTo(mobileConnectionInfo)
+ assertThat(underTest.operatorAlphaShort.value).isEqualTo(nonCarrierMergedName)
verify(carrierMergedFactory, never()).build(SUB_ID, tableLogBuffer)
}
@@ -156,39 +155,40 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
testScope.runTest {
initializeRepo(startingIsCarrierMerged = false)
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ var latestName: String? = null
+ var latestLevel: Int? = null
+
+ val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this)
+ val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
underTest.setIsCarrierMerged(true)
- val info1 =
- MobileConnectionModel(
- operatorAlphaShort = "Carrier Merged Operator",
- primaryLevel = 1,
- )
- carrierMergedRepo.setConnectionInfo(info1)
+ val operator1 = "Carrier Merged Operator"
+ val level1 = 1
+ carrierMergedRepo.operatorAlphaShort.value = operator1
+ carrierMergedRepo.primaryLevel.value = level1
- assertThat(latest).isEqualTo(info1)
+ assertThat(latestName).isEqualTo(operator1)
+ assertThat(latestLevel).isEqualTo(level1)
- val info2 =
- MobileConnectionModel(
- operatorAlphaShort = "Carrier Merged Operator #2",
- primaryLevel = 2,
- )
- carrierMergedRepo.setConnectionInfo(info2)
+ val operator2 = "Carrier Merged Operator #2"
+ val level2 = 2
+ carrierMergedRepo.operatorAlphaShort.value = operator2
+ carrierMergedRepo.primaryLevel.value = level2
- assertThat(latest).isEqualTo(info2)
+ assertThat(latestName).isEqualTo(operator2)
+ assertThat(latestLevel).isEqualTo(level2)
- val info3 =
- MobileConnectionModel(
- operatorAlphaShort = "Carrier Merged Operator #3",
- primaryLevel = 3,
- )
- carrierMergedRepo.setConnectionInfo(info3)
+ val operator3 = "Carrier Merged Operator #3"
+ val level3 = 3
+ carrierMergedRepo.operatorAlphaShort.value = operator3
+ carrierMergedRepo.primaryLevel.value = level3
- assertThat(latest).isEqualTo(info3)
+ assertThat(latestName).isEqualTo(operator3)
+ assertThat(latestLevel).isEqualTo(level3)
- job.cancel()
+ nameJob.cancel()
+ levelJob.cancel()
}
@Test
@@ -196,39 +196,40 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
testScope.runTest {
initializeRepo(startingIsCarrierMerged = false)
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ var latestName: String? = null
+ var latestLevel: Int? = null
+
+ val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this)
+ val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
underTest.setIsCarrierMerged(false)
- val info1 =
- MobileConnectionModel(
- operatorAlphaShort = "Typical Merged Operator",
- primaryLevel = 1,
- )
- mobileRepo.setConnectionInfo(info1)
+ val operator1 = "Typical Merged Operator"
+ val level1 = 1
+ mobileRepo.operatorAlphaShort.value = operator1
+ mobileRepo.primaryLevel.value = level1
- assertThat(latest).isEqualTo(info1)
+ assertThat(latestName).isEqualTo(operator1)
+ assertThat(latestLevel).isEqualTo(level1)
- val info2 =
- MobileConnectionModel(
- operatorAlphaShort = "Typical Merged Operator #2",
- primaryLevel = 2,
- )
- mobileRepo.setConnectionInfo(info2)
+ val operator2 = "Typical Merged Operator #2"
+ val level2 = 2
+ mobileRepo.operatorAlphaShort.value = operator2
+ mobileRepo.primaryLevel.value = level2
- assertThat(latest).isEqualTo(info2)
+ assertThat(latestName).isEqualTo(operator2)
+ assertThat(latestLevel).isEqualTo(level2)
- val info3 =
- MobileConnectionModel(
- operatorAlphaShort = "Typical Merged Operator #3",
- primaryLevel = 3,
- )
- mobileRepo.setConnectionInfo(info3)
+ val operator3 = "Typical Merged Operator #3"
+ val level3 = 3
+ mobileRepo.operatorAlphaShort.value = operator3
+ mobileRepo.primaryLevel.value = level3
- assertThat(latest).isEqualTo(info3)
+ assertThat(latestName).isEqualTo(operator3)
+ assertThat(latestLevel).isEqualTo(level3)
- job.cancel()
+ nameJob.cancel()
+ levelJob.cancel()
}
@Test
@@ -236,57 +237,58 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
testScope.runTest {
initializeRepo(startingIsCarrierMerged = false)
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ var latestName: String? = null
+ var latestLevel: Int? = null
- val carrierMergedInfo =
- MobileConnectionModel(
- operatorAlphaShort = "Carrier Merged Operator",
- primaryLevel = 4,
- )
- carrierMergedRepo.setConnectionInfo(carrierMergedInfo)
+ val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this)
+ val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
- val mobileInfo =
- MobileConnectionModel(
- operatorAlphaShort = "Typical Operator",
- primaryLevel = 2,
- )
- mobileRepo.setConnectionInfo(mobileInfo)
+ val carrierMergedOperator = "Carrier Merged Operator"
+ val carrierMergedLevel = 4
+ carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperator
+ carrierMergedRepo.primaryLevel.value = carrierMergedLevel
+
+ val mobileName = "Typical Operator"
+ val mobileLevel = 2
+ mobileRepo.operatorAlphaShort.value = mobileName
+ mobileRepo.primaryLevel.value = mobileLevel
// Start with the mobile info
- assertThat(latest).isEqualTo(mobileInfo)
+ assertThat(latestName).isEqualTo(mobileName)
+ assertThat(latestLevel).isEqualTo(mobileLevel)
// WHEN isCarrierMerged is set to true
underTest.setIsCarrierMerged(true)
// THEN the carrier merged info is used
- assertThat(latest).isEqualTo(carrierMergedInfo)
+ assertThat(latestName).isEqualTo(carrierMergedOperator)
+ assertThat(latestLevel).isEqualTo(carrierMergedLevel)
- val newCarrierMergedInfo =
- MobileConnectionModel(
- operatorAlphaShort = "New CM Operator",
- primaryLevel = 0,
- )
- carrierMergedRepo.setConnectionInfo(newCarrierMergedInfo)
+ val newCarrierMergedName = "New CM Operator"
+ val newCarrierMergedLevel = 0
+ carrierMergedRepo.operatorAlphaShort.value = newCarrierMergedName
+ carrierMergedRepo.primaryLevel.value = newCarrierMergedLevel
- assertThat(latest).isEqualTo(newCarrierMergedInfo)
+ assertThat(latestName).isEqualTo(newCarrierMergedName)
+ assertThat(latestLevel).isEqualTo(newCarrierMergedLevel)
// WHEN isCarrierMerged is set to false
underTest.setIsCarrierMerged(false)
// THEN the typical info is used
- assertThat(latest).isEqualTo(mobileInfo)
+ assertThat(latestName).isEqualTo(mobileName)
+ assertThat(latestLevel).isEqualTo(mobileLevel)
- val newMobileInfo =
- MobileConnectionModel(
- operatorAlphaShort = "New Mobile Operator",
- primaryLevel = 3,
- )
- mobileRepo.setConnectionInfo(newMobileInfo)
+ val newMobileName = "New MobileOperator"
+ val newMobileLevel = 3
+ mobileRepo.operatorAlphaShort.value = newMobileName
+ mobileRepo.primaryLevel.value = newMobileLevel
- assertThat(latest).isEqualTo(newMobileInfo)
+ assertThat(latestName).isEqualTo(newMobileName)
+ assertThat(latestLevel).isEqualTo(newMobileLevel)
- job.cancel()
+ nameJob.cancel()
+ levelJob.cancel()
}
@Test
@@ -370,7 +372,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
initializeRepo(startingIsCarrierMerged = false)
- val job = underTest.connectionInfo.launchIn(this)
+ val emergencyJob = underTest.isEmergencyOnly.launchIn(this)
+ val operatorJob = underTest.operatorAlphaShort.launchIn(this)
// WHEN we set up some mobile connection info
val serviceState = ServiceState()
@@ -394,7 +397,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
assertThat(dumpBuffer()).contains("$COL_OPERATOR${BUFFER_SEPARATOR}OpDiff")
assertThat(dumpBuffer()).contains("$COL_EMERGENCY${BUFFER_SEPARATOR}true")
- job.cancel()
+ emergencyJob.cancel()
+ operatorJob.cancel()
}
@Test
@@ -409,7 +413,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
initializeRepo(startingIsCarrierMerged = true)
- val job = underTest.connectionInfo.launchIn(this)
+ val job = underTest.primaryLevel.launchIn(this)
// WHEN we set up carrier merged info
val networkId = 2
@@ -452,7 +456,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
initializeRepo(startingIsCarrierMerged = false)
- val job = underTest.connectionInfo.launchIn(this)
+ val job = underTest.primaryLevel.launchIn(this)
// WHEN we set up some mobile connection info
val signalStrength = mock<SignalStrength>()
@@ -502,12 +506,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
assertThat(bufferAfterCarrierMerged).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}1")
// WHEN the normal network is updated
- val newMobileInfo =
- MobileConnectionModel(
- operatorAlphaShort = "Mobile Operator 2",
- primaryLevel = 0,
- )
- mobileRepo.setConnectionInfo(newMobileInfo)
+ mobileRepo.primaryLevel.value = 0
// THEN the new level is logged
assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}0")
@@ -529,7 +528,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
// WHEN isCarrierMerged = false
initializeRepo(startingIsCarrierMerged = false)
- val job = underTest.connectionInfo.launchIn(this)
+ val job = underTest.primaryLevel.launchIn(this)
val signalStrength = mock<SignalStrength>()
whenever(signalStrength.level).thenReturn(1)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
index b2577e349da7..542b688b162d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
@@ -18,17 +18,16 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
import android.content.Intent
import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL
-import android.telephony.CellSignalStrengthCdma
import android.telephony.NetworkRegistrationInfo
import android.telephony.ServiceState
import android.telephony.ServiceState.STATE_IN_SERVICE
import android.telephony.ServiceState.STATE_OUT_OF_SERVICE
-import android.telephony.SignalStrength
import android.telephony.TelephonyCallback
import android.telephony.TelephonyCallback.DataActivityListener
import android.telephony.TelephonyCallback.ServiceStateListener
import android.telephony.TelephonyDisplayInfo
import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA
+import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
import android.telephony.TelephonyManager
import android.telephony.TelephonyManager.DATA_ACTIVITY_DORMANT
import android.telephony.TelephonyManager.DATA_ACTIVITY_IN
@@ -50,12 +49,15 @@ import android.telephony.TelephonyManager.EXTRA_SHOW_SPN
import android.telephony.TelephonyManager.EXTRA_SPN
import android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID
import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
+import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
import androidx.test.filters.SmallTest
+import com.android.settingslib.mobile.MobileMappings
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType
@@ -65,7 +67,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrier
import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.signalStrength
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
@@ -73,14 +75,12 @@ import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.runBlocking
-import org.junit.After
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
@@ -97,7 +97,6 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
@Mock private lateinit var logger: MobileInputLogger
@Mock private lateinit var tableLogger: TableLogBuffer
- private val scope = CoroutineScope(IMMEDIATE)
private val mobileMappings = FakeMobileMappingsProxy()
private val systemUiCarrierConfig =
SystemUiCarrierConfig(
@@ -105,6 +104,9 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
createTestConfig(),
)
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -122,265 +124,312 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
systemUiCarrierConfig,
fakeBroadcastDispatcher,
mobileMappings,
- IMMEDIATE,
+ testDispatcher,
logger,
tableLogger,
- scope,
+ testScope.backgroundScope,
)
}
- @After
- fun tearDown() {
- scope.cancel()
- }
+ @Test
+ fun emergencyOnly() =
+ testScope.runTest {
+ var latest: Boolean? = null
+ val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this)
+
+ val serviceState = ServiceState()
+ serviceState.isEmergencyOnly = true
+
+ getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
+
+ assertThat(latest).isEqualTo(true)
+
+ job.cancel()
+ }
@Test
- fun testFlowForSubId_default() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun emergencyOnly_toggles() =
+ testScope.runTest {
+ var latest: Boolean? = null
+ val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this)
- assertThat(latest).isEqualTo(MobileConnectionModel())
+ val callback = getTelephonyCallbackForType<ServiceStateListener>()
+ callback.onServiceStateChanged(ServiceState().also { it.isEmergencyOnly = true })
+ assertThat(latest).isTrue()
+
+ callback.onServiceStateChanged(ServiceState().also { it.isEmergencyOnly = false })
+
+ assertThat(latest).isFalse()
job.cancel()
}
@Test
- fun testFlowForSubId_emergencyOnly() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun cdmaLevelUpdates() =
+ testScope.runTest {
+ var latest: Int? = null
+ val job = underTest.cdmaLevel.onEach { latest = it }.launchIn(this)
- val serviceState = ServiceState()
- serviceState.isEmergencyOnly = true
+ val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
+ var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
+ callback.onSignalStrengthsChanged(strength)
- getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
+ assertThat(latest).isEqualTo(2)
+
+ // gsmLevel updates, no change to cdmaLevel
+ strength = signalStrength(gsmLevel = 3, cdmaLevel = 2, isGsm = true)
- assertThat(latest?.isEmergencyOnly).isEqualTo(true)
+ assertThat(latest).isEqualTo(2)
job.cancel()
}
@Test
- fun testFlowForSubId_emergencyOnly_toggles() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun gsmLevelUpdates() =
+ testScope.runTest {
+ var latest: Int? = null
+ val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
- val callback = getTelephonyCallbackForType<ServiceStateListener>()
- val serviceState = ServiceState()
- serviceState.isEmergencyOnly = true
- callback.onServiceStateChanged(serviceState)
- serviceState.isEmergencyOnly = false
- callback.onServiceStateChanged(serviceState)
+ val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
+ var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
+ callback.onSignalStrengthsChanged(strength)
+
+ assertThat(latest).isEqualTo(1)
+
+ strength = signalStrength(gsmLevel = 3, cdmaLevel = 2, isGsm = true)
+ callback.onSignalStrengthsChanged(strength)
- assertThat(latest?.isEmergencyOnly).isEqualTo(false)
+ assertThat(latest).isEqualTo(3)
job.cancel()
}
@Test
- fun testFlowForSubId_signalStrengths_levelsUpdate() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun isGsm() =
+ testScope.runTest {
+ var latest: Boolean? = null
+ val job = underTest.isGsm.onEach { latest = it }.launchIn(this)
val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
- val strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
+ var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
callback.onSignalStrengthsChanged(strength)
- assertThat(latest?.isGsm).isEqualTo(true)
- assertThat(latest?.primaryLevel).isEqualTo(1)
- assertThat(latest?.cdmaLevel).isEqualTo(2)
+ assertThat(latest).isTrue()
+
+ strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = false)
+ callback.onSignalStrengthsChanged(strength)
+
+ assertThat(latest).isFalse()
job.cancel()
}
@Test
- fun testFlowForSubId_dataConnectionState_connected() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun dataConnectionState_connected() =
+ testScope.runTest {
+ var latest: DataConnectionState? = null
+ val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
val callback =
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
callback.onDataConnectionStateChanged(DATA_CONNECTED, 200 /* unused */)
- assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Connected)
+ assertThat(latest).isEqualTo(DataConnectionState.Connected)
job.cancel()
}
@Test
- fun testFlowForSubId_dataConnectionState_connecting() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun dataConnectionState_connecting() =
+ testScope.runTest {
+ var latest: DataConnectionState? = null
+ val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
val callback =
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
callback.onDataConnectionStateChanged(DATA_CONNECTING, 200 /* unused */)
- assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Connecting)
+ assertThat(latest).isEqualTo(DataConnectionState.Connecting)
job.cancel()
}
@Test
- fun testFlowForSubId_dataConnectionState_disconnected() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun dataConnectionState_disconnected() =
+ testScope.runTest {
+ var latest: DataConnectionState? = null
+ val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
val callback =
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
callback.onDataConnectionStateChanged(DATA_DISCONNECTED, 200 /* unused */)
- assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Disconnected)
+ assertThat(latest).isEqualTo(DataConnectionState.Disconnected)
job.cancel()
}
@Test
- fun testFlowForSubId_dataConnectionState_disconnecting() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun dataConnectionState_disconnecting() =
+ testScope.runTest {
+ var latest: DataConnectionState? = null
+ val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
val callback =
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
callback.onDataConnectionStateChanged(DATA_DISCONNECTING, 200 /* unused */)
- assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Disconnecting)
+ assertThat(latest).isEqualTo(DataConnectionState.Disconnecting)
job.cancel()
}
@Test
- fun testFlowForSubId_dataConnectionState_suspended() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun dataConnectionState_suspended() =
+ testScope.runTest {
+ var latest: DataConnectionState? = null
+ val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
val callback =
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
callback.onDataConnectionStateChanged(DATA_SUSPENDED, 200 /* unused */)
- assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Suspended)
+ assertThat(latest).isEqualTo(DataConnectionState.Suspended)
job.cancel()
}
@Test
- fun testFlowForSubId_dataConnectionState_handoverInProgress() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun dataConnectionState_handoverInProgress() =
+ testScope.runTest {
+ var latest: DataConnectionState? = null
+ val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
val callback =
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
callback.onDataConnectionStateChanged(DATA_HANDOVER_IN_PROGRESS, 200 /* unused */)
- assertThat(latest?.dataConnectionState)
- .isEqualTo(DataConnectionState.HandoverInProgress)
+ assertThat(latest).isEqualTo(DataConnectionState.HandoverInProgress)
job.cancel()
}
@Test
- fun testFlowForSubId_dataConnectionState_unknown() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun dataConnectionState_unknown() =
+ testScope.runTest {
+ var latest: DataConnectionState? = null
+ val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
val callback =
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
callback.onDataConnectionStateChanged(DATA_UNKNOWN, 200 /* unused */)
- assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Unknown)
+ assertThat(latest).isEqualTo(DataConnectionState.Unknown)
job.cancel()
}
@Test
- fun testFlowForSubId_dataConnectionState_invalid() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun dataConnectionState_invalid() =
+ testScope.runTest {
+ var latest: DataConnectionState? = null
+ val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
val callback =
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
callback.onDataConnectionStateChanged(45, 200 /* unused */)
- assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Invalid)
+ assertThat(latest).isEqualTo(DataConnectionState.Invalid)
job.cancel()
}
@Test
- fun testFlowForSubId_dataActivity() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun dataActivity() =
+ testScope.runTest {
+ var latest: DataActivityModel? = null
+ val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
val callback = getTelephonyCallbackForType<DataActivityListener>()
callback.onDataActivity(DATA_ACTIVITY_INOUT)
- assertThat(latest?.dataActivityDirection)
- .isEqualTo(DATA_ACTIVITY_INOUT.toMobileDataActivityModel())
+ assertThat(latest).isEqualTo(DATA_ACTIVITY_INOUT.toMobileDataActivityModel())
job.cancel()
}
@Test
- fun testFlowForSubId_carrierNetworkChange() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun carrierNetworkChange() =
+ testScope.runTest {
+ var latest: Boolean? = null
+ val job = underTest.carrierNetworkChangeActive.onEach { latest = it }.launchIn(this)
val callback = getTelephonyCallbackForType<TelephonyCallback.CarrierNetworkListener>()
callback.onCarrierNetworkChange(true)
- assertThat(latest?.carrierNetworkChangeActive).isEqualTo(true)
+ assertThat(latest).isEqualTo(true)
job.cancel()
}
@Test
- fun subscriptionFlow_networkType_default() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun networkType_default() =
+ testScope.runTest {
+ var latest: ResolvedNetworkType? = null
+ val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
val expected = UnknownNetworkType
- assertThat(latest?.resolvedNetworkType).isEqualTo(expected)
+ assertThat(latest).isEqualTo(expected)
+
+ job.cancel()
+ }
+
+ @Test
+ fun networkType_unknown_hasCorrectKey() =
+ testScope.runTest {
+ var latest: ResolvedNetworkType? = null
+ val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
+
+ val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
+ val type = NETWORK_TYPE_UNKNOWN
+ val expected = UnknownNetworkType
+ val ti = mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type) }
+ callback.onDisplayInfoChanged(ti)
+
+ assertThat(latest).isEqualTo(expected)
+ assertThat(latest!!.lookupKey).isEqualTo(MobileMappings.toIconKey(type))
job.cancel()
}
@Test
- fun subscriptionFlow_networkType_updatesUsingDefault() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun networkType_updatesUsingDefault() =
+ testScope.runTest {
+ var latest: ResolvedNetworkType? = null
+ val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
+ val overrideType = OVERRIDE_NETWORK_TYPE_NONE
val type = NETWORK_TYPE_LTE
val expected = DefaultNetworkType(mobileMappings.toIconKey(type))
- val ti = mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type) }
+ val ti =
+ mock<TelephonyDisplayInfo>().also {
+ whenever(it.overrideNetworkType).thenReturn(overrideType)
+ whenever(it.networkType).thenReturn(type)
+ }
callback.onDisplayInfoChanged(ti)
- assertThat(latest?.resolvedNetworkType).isEqualTo(expected)
+ assertThat(latest).isEqualTo(expected)
job.cancel()
}
@Test
- fun subscriptionFlow_networkType_updatesUsingOverride() =
- runBlocking(IMMEDIATE) {
- var latest: MobileConnectionModel? = null
- val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+ fun networkType_updatesUsingOverride() =
+ testScope.runTest {
+ var latest: ResolvedNetworkType? = null
+ val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
val type = OVERRIDE_NETWORK_TYPE_LTE_CA
@@ -392,22 +441,44 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
}
callback.onDisplayInfoChanged(ti)
- assertThat(latest?.resolvedNetworkType).isEqualTo(expected)
+ assertThat(latest).isEqualTo(expected)
+
+ job.cancel()
+ }
+
+ @Test
+ fun networkType_unknownNetworkWithOverride_usesOverrideKey() =
+ testScope.runTest {
+ var latest: ResolvedNetworkType? = null
+ val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
+
+ val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
+ val unknown = NETWORK_TYPE_UNKNOWN
+ val type = OVERRIDE_NETWORK_TYPE_LTE_CA
+ val expected = OverrideNetworkType(mobileMappings.toIconKeyOverride(type))
+ val ti =
+ mock<TelephonyDisplayInfo>().also {
+ whenever(it.networkType).thenReturn(unknown)
+ whenever(it.overrideNetworkType).thenReturn(type)
+ }
+ callback.onDisplayInfoChanged(ti)
+
+ assertThat(latest).isEqualTo(expected)
job.cancel()
}
@Test
fun dataEnabled_initial_false() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
whenever(telephonyManager.isDataConnectionAllowed).thenReturn(false)
assertThat(underTest.dataEnabled.value).isFalse()
}
@Test
- fun `is data enabled - tracks telephony callback`() =
- runBlocking(IMMEDIATE) {
+ fun isDataEnabled_tracksTelephonyCallback() =
+ testScope.runTest {
var latest: Boolean? = null
val job = underTest.dataEnabled.onEach { latest = it }.launchIn(this)
@@ -427,7 +498,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
@Test
fun numberOfLevels_isDefault() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
var latest: Int? = null
val job = underTest.numberOfLevels.onEach { latest = it }.launchIn(this)
@@ -437,51 +508,68 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `roaming - cdma - queries telephony manager`() =
- runBlocking(IMMEDIATE) {
+ fun roaming_cdma_queriesTelephonyManager() =
+ testScope.runTest {
var latest: Boolean? = null
val job = underTest.cdmaRoaming.onEach { latest = it }.launchIn(this)
val cb = getTelephonyCallbackForType<ServiceStateListener>()
- val serviceState = ServiceState()
- serviceState.roaming = false
-
- // CDMA roaming is off, GSM roaming is off
+ // CDMA roaming is off, GSM roaming is on
whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(ERI_OFF)
- cb.onServiceStateChanged(serviceState)
+ cb.onServiceStateChanged(ServiceState().also { it.roaming = true })
assertThat(latest).isFalse()
- // CDMA roaming is off, GSM roaming is on
+ // CDMA roaming is on, GSM roaming is off
whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(ERI_ON)
- cb.onServiceStateChanged(serviceState)
+ cb.onServiceStateChanged(ServiceState().also { it.roaming = false })
assertThat(latest).isTrue()
job.cancel()
}
+ /**
+ * [TelephonyManager.getCdmaEnhancedRoamingIndicatorDisplayNumber] returns -1 if the service is
+ * not running or if there is an error while retrieving the cdma ERI
+ */
@Test
- fun `roaming - gsm - queries service state`() =
- runBlocking(IMMEDIATE) {
+ fun cdmaRoaming_ignoresNegativeOne() =
+ testScope.runTest {
var latest: Boolean? = null
- val job = underTest.connectionInfo.onEach { latest = it.isRoaming }.launchIn(this)
+ val job = underTest.cdmaRoaming.onEach { latest = it }.launchIn(this)
val serviceState = ServiceState()
serviceState.roaming = false
val cb = getTelephonyCallbackForType<ServiceStateListener>()
+ // CDMA roaming is unavailable (-1), GSM roaming is off
+ whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(-1)
+ cb.onServiceStateChanged(serviceState)
+
+ assertThat(latest).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun roaming_gsm_queriesServiceState() =
+ testScope.runTest {
+ var latest: Boolean? = null
+ val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
+
+ val cb = getTelephonyCallbackForType<ServiceStateListener>()
+
// CDMA roaming is off, GSM roaming is off
whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(ERI_OFF)
- cb.onServiceStateChanged(serviceState)
+ cb.onServiceStateChanged(ServiceState().also { it.roaming = false })
assertThat(latest).isFalse()
// CDMA roaming is off, GSM roaming is on
- serviceState.roaming = true
- cb.onServiceStateChanged(serviceState)
+ cb.onServiceStateChanged(ServiceState().also { it.roaming = true })
assertThat(latest).isTrue()
@@ -489,11 +577,10 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `activity - updates from callback`() =
- runBlocking(IMMEDIATE) {
+ fun activity_updatesFromCallback() =
+ testScope.runTest {
var latest: DataActivityModel? = null
- val job =
- underTest.connectionInfo.onEach { latest = it.dataActivityDirection }.launchIn(this)
+ val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
assertThat(latest)
.isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
@@ -527,8 +614,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `network name - default`() =
- runBlocking(IMMEDIATE) {
+ fun networkName_default() =
+ testScope.runTest {
var latest: NetworkNameModel? = null
val job = underTest.networkName.onEach { latest = it }.launchIn(this)
@@ -538,8 +625,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `network name - uses broadcast info - returns derived`() =
- runBlocking(IMMEDIATE) {
+ fun networkName_usesBroadcastInfo_returnsDerived() =
+ testScope.runTest {
var latest: NetworkNameModel? = null
val job = underTest.networkName.onEach { latest = it }.launchIn(this)
@@ -555,8 +642,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `network name - broadcast not for this sub id - keeps old value`() =
- runBlocking(IMMEDIATE) {
+ fun networkName_broadcastNotForThisSubId_keepsOldValue() =
+ testScope.runTest {
var latest: NetworkNameModel? = null
val job = underTest.networkName.onEach { latest = it }.launchIn(this)
@@ -580,8 +667,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `network name - broadcast has no data - updates to default`() =
- runBlocking(IMMEDIATE) {
+ fun networkName_broadcastHasNoData_updatesToDefault() =
+ testScope.runTest {
var latest: NetworkNameModel? = null
val job = underTest.networkName.onEach { latest = it }.launchIn(this)
@@ -607,12 +694,11 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `operatorAlphaShort - tracked`() =
- runBlocking(IMMEDIATE) {
+ fun operatorAlphaShort_tracked() =
+ testScope.runTest {
var latest: String? = null
- val job =
- underTest.connectionInfo.onEach { latest = it.operatorAlphaShort }.launchIn(this)
+ val job = underTest.operatorAlphaShort.onEach { latest = it }.launchIn(this)
val shortName = "short name"
val serviceState = ServiceState()
@@ -630,35 +716,47 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `connection model - isInService - not iwlan`() =
- runBlocking(IMMEDIATE) {
+ fun isInService_notIwlan() =
+ testScope.runTest {
var latest: Boolean? = null
- val job = underTest.connectionInfo.onEach { latest = it.isInService }.launchIn(this)
-
- val serviceState = ServiceState()
- serviceState.voiceRegState = STATE_IN_SERVICE
- serviceState.dataRegState = STATE_IN_SERVICE
-
- getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
+ val job = underTest.isInService.onEach { latest = it }.launchIn(this)
+
+ getTelephonyCallbackForType<ServiceStateListener>()
+ .onServiceStateChanged(
+ ServiceState().also {
+ it.voiceRegState = STATE_IN_SERVICE
+ it.dataRegState = STATE_IN_SERVICE
+ }
+ )
assertThat(latest).isTrue()
- serviceState.voiceRegState = STATE_OUT_OF_SERVICE
- getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
+ getTelephonyCallbackForType<ServiceStateListener>()
+ .onServiceStateChanged(
+ ServiceState().also {
+ it.dataRegState = STATE_IN_SERVICE
+ it.voiceRegState = STATE_OUT_OF_SERVICE
+ }
+ )
assertThat(latest).isTrue()
- serviceState.dataRegState = STATE_OUT_OF_SERVICE
- getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
+ getTelephonyCallbackForType<ServiceStateListener>()
+ .onServiceStateChanged(
+ ServiceState().also {
+ it.voiceRegState = STATE_OUT_OF_SERVICE
+ it.dataRegState = STATE_OUT_OF_SERVICE
+ }
+ )
assertThat(latest).isFalse()
job.cancel()
}
@Test
- fun `connection model - isInService - is iwlan - voice out of service - data in service`() =
- runBlocking(IMMEDIATE) {
+ fun isInService_isIwlan_voiceOutOfService_dataInService() =
+ testScope.runTest {
var latest: Boolean? = null
- val job = underTest.connectionInfo.onEach { latest = it.isInService }.launchIn(this)
+ val job = underTest.isInService.onEach { latest = it }.launchIn(this)
// Mock the service state here so we can make it specifically IWLAN
val serviceState: ServiceState = mock()
@@ -680,8 +778,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `number of levels - uses carrier config`() =
- runBlocking(IMMEDIATE) {
+ fun numberOfLevels_usesCarrierConfig() =
+ testScope.runTest {
var latest: Int? = null
val job = underTest.numberOfLevels.onEach { latest = it }.launchIn(this)
@@ -706,19 +804,6 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
return MobileTelephonyHelpers.getTelephonyCallbackForType(telephonyManager)
}
- /** Convenience constructor for SignalStrength */
- private fun signalStrength(gsmLevel: Int, cdmaLevel: Int, isGsm: Boolean): SignalStrength {
- val signalStrength = mock<SignalStrength>()
- whenever(signalStrength.isGsm).thenReturn(isGsm)
- whenever(signalStrength.level).thenReturn(gsmLevel)
- val cdmaStrength =
- mock<CellSignalStrengthCdma>().also { whenever(it.level).thenReturn(cdmaLevel) }
- whenever(signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java))
- .thenReturn(listOf(cdmaStrength))
-
- return signalStrength
- }
-
private fun spnIntent(
subId: Int = SUB_1_ID,
showSpn: Boolean = true,
@@ -735,7 +820,6 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
}
companion object {
- private val IMMEDIATE = Dispatchers.Main.immediate
private const val SUB_1_ID = 1
private val DEFAULT_NAME = NetworkNameModel.Default("default name")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt
new file mode 100644
index 000000000000..bbf04ed28fd7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt
@@ -0,0 +1,341 @@
+/*
+ * 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.statusbar.pipeline.mobile.data.repository.prod
+
+import android.telephony.ServiceState
+import android.telephony.TelephonyCallback
+import android.telephony.TelephonyCallback.CarrierNetworkListener
+import android.telephony.TelephonyCallback.DataActivityListener
+import android.telephony.TelephonyCallback.DataConnectionStateListener
+import android.telephony.TelephonyCallback.DataEnabledListener
+import android.telephony.TelephonyCallback.DisplayInfoListener
+import android.telephony.TelephonyCallback.ServiceStateListener
+import android.telephony.TelephonyDisplayInfo
+import android.telephony.TelephonyManager
+import android.telephony.TelephonyManager.DATA_ACTIVITY_INOUT
+import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
+import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
+import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.getTelephonyCallbackForType
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.signalStrength
+import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+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
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+/**
+ * Test class to stress test the TelephonyCallbacks that we listen to. In particular, the callbacks
+ * all come back in on a single listener (for reasons defined in the system). This test is built to
+ * ensure that we don't miss any important callbacks.
+ *
+ * Kind of like an interaction test case build just for [TelephonyCallback]
+ *
+ * The list of telephony callbacks we use is: [TelephonyCallback.CarrierNetworkListener]
+ * [TelephonyCallback.DataActivityListener] [TelephonyCallback.DataConnectionStateListener]
+ * [TelephonyCallback.DataEnabledListener] [TelephonyCallback.DisplayInfoListener]
+ * [TelephonyCallback.ServiceStateListener] [TelephonyCallback.SignalStrengthsListener]
+ *
+ * Because each of these callbacks comes in on the same callbackFlow, collecting on a field backed
+ * by only a single callback can immediately create backpressure on the other fields related to a
+ * mobile connection.
+ *
+ * This test should be designed to test _at least_ each individual callback in a smoke-test fashion.
+ * The way we will achieve this is as follows:
+ * 1. Start up a listener (A) collecting on a field which is _not under test_
+ * 2. Send a single event to a telephony callback which supports the field under test (B)
+ * 3. Send many (may be as few as 2) events to the callback backing A to ensure we start seeing
+ * backpressure on other fields NOTE: poor handling of backpressure here would normally cause B
+ * to get dropped
+ * 4. Start up a new collector for B
+ * 5. Assert that B has the state sent in step #2
+ */
+@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+class MobileConnectionTelephonySmokeTests : SysuiTestCase() {
+ private lateinit var underTest: MobileConnectionRepositoryImpl
+ private lateinit var connectionsRepo: FakeMobileConnectionsRepository
+
+ @Mock private lateinit var telephonyManager: TelephonyManager
+ @Mock private lateinit var logger: MobileInputLogger
+ @Mock private lateinit var tableLogger: TableLogBuffer
+
+ private val mobileMappings = FakeMobileMappingsProxy()
+ private val systemUiCarrierConfig =
+ SystemUiCarrierConfig(
+ SUB_1_ID,
+ SystemUiCarrierConfigTest.createTestConfig(),
+ )
+
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(telephonyManager.subscriptionId).thenReturn(SUB_1_ID)
+
+ connectionsRepo = FakeMobileConnectionsRepository(mobileMappings, tableLogger)
+
+ underTest =
+ MobileConnectionRepositoryImpl(
+ context,
+ SUB_1_ID,
+ DEFAULT_NAME,
+ SEP,
+ telephonyManager,
+ systemUiCarrierConfig,
+ fakeBroadcastDispatcher,
+ mobileMappings,
+ testDispatcher,
+ logger,
+ tableLogger,
+ testScope.backgroundScope,
+ )
+ }
+
+ @Test
+ fun carrierNetworkChangeListener_noisyActivity() =
+ testScope.runTest {
+ var latest: Boolean? = null
+
+ // Start collecting data activity; don't care about the result
+ val activityJob = underTest.dataActivityDirection.launchIn(this)
+ val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+ val callback = getTelephonyCallbackForType<CarrierNetworkListener>()
+ callback.onCarrierNetworkChange(true)
+
+ flipActivity(100, activityCallback)
+
+ val job = underTest.carrierNetworkChangeActive.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isTrue()
+
+ activityJob.cancel()
+ job.cancel()
+ }
+
+ @Test
+ fun dataActivityLate_noisyDisplayInfo() =
+ testScope.runTest {
+ var latest: DataActivityModel? = null
+
+ // start collecting displayInfo; don't care about the result
+ val displayInfoJob = underTest.resolvedNetworkType.launchIn(this)
+
+ val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+ activityCallback.onDataActivity(DATA_ACTIVITY_INOUT)
+
+ val displayInfoCallback = getTelephonyCallbackForType<DisplayInfoListener>()
+ val type1 = NETWORK_TYPE_UNKNOWN
+ val type2 = NETWORK_TYPE_LTE
+ val t1 =
+ mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type1) }
+ val t2 =
+ mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type2) }
+
+ flipDisplayInfo(100, listOf(t1, t2), displayInfoCallback)
+
+ val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest)
+ .isEqualTo(
+ DataActivityModel(
+ hasActivityIn = true,
+ hasActivityOut = true,
+ )
+ )
+
+ displayInfoJob.cancel()
+ job.cancel()
+ }
+
+ @Test
+ fun dataConnectionStateListener_noisyActivity() =
+ testScope.runTest {
+ var latest: DataConnectionState? = null
+
+ // Start collecting data activity; don't care about the result
+ val activityJob = underTest.dataActivityDirection.launchIn(this)
+
+ val connectionCallback = getTelephonyCallbackForType<DataConnectionStateListener>()
+ val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+ connectionCallback.onDataConnectionStateChanged(
+ TelephonyManager.DATA_CONNECTED,
+ 200 /* unused */
+ )
+
+ // Send a bunch of events that we don't care about, to overrun the replay buffer
+ flipActivity(100, activityCallback)
+
+ val connectionJob = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isEqualTo(DataConnectionState.Connected)
+
+ activityJob.cancel()
+ connectionJob.cancel()
+ }
+
+ @Test
+ fun dataEnabledLate_noisyActivity() =
+ testScope.runTest {
+ var latest: Boolean? = null
+
+ // Start collecting data activity; don't care about the result
+ val activityJob = underTest.dataActivityDirection.launchIn(this)
+
+ val enabledCallback = getTelephonyCallbackForType<DataEnabledListener>()
+ val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+ enabledCallback.onDataEnabledChanged(true, 1 /* unused */)
+
+ // Send a bunch of events that we don't care about, to overrun the replay buffer
+ flipActivity(100, activityCallback)
+
+ val job = underTest.dataEnabled.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isTrue()
+
+ activityJob.cancel()
+ job.cancel()
+ }
+
+ @Test
+ fun displayInfoLate_noisyActivity() =
+ testScope.runTest {
+ var latest: ResolvedNetworkType? = null
+
+ // Start collecting data activity; don't care about the result
+ val activityJob = underTest.dataActivityDirection.launchIn(this)
+
+ val displayInfoCallback = getTelephonyCallbackForType<DisplayInfoListener>()
+ val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+ val type = NETWORK_TYPE_LTE
+ val expected = ResolvedNetworkType.DefaultNetworkType(mobileMappings.toIconKey(type))
+ val ti = mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type) }
+ displayInfoCallback.onDisplayInfoChanged(ti)
+
+ // Send a bunch of events that we don't care about, to overrun the replay buffer
+ flipActivity(100, activityCallback)
+
+ val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isEqualTo(expected)
+
+ activityJob.cancel()
+ job.cancel()
+ }
+
+ @Test
+ fun serviceStateListener_noisyActivity() =
+ testScope.runTest {
+ var latest: Boolean? = null
+
+ // Start collecting data activity; don't care about the result
+ val activityJob = underTest.dataActivityDirection.launchIn(this)
+
+ val serviceStateCallback = getTelephonyCallbackForType<ServiceStateListener>()
+ val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+ // isEmergencyOnly comes in
+ val serviceState = ServiceState()
+ serviceState.isEmergencyOnly = true
+ serviceStateCallback.onServiceStateChanged(serviceState)
+
+ flipActivity(100, activityCallback)
+
+ val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isTrue()
+
+ activityJob.cancel()
+ job.cancel()
+ }
+
+ @Test
+ fun signalStrengthsListenerLate_noisyActivity() =
+ testScope.runTest {
+ var latest: Int? = null
+
+ // Start collecting data activity; don't care about the result
+ val activityJob = underTest.dataActivityDirection.launchIn(this)
+ val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+ val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
+ val strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
+ callback.onSignalStrengthsChanged(strength)
+
+ flipActivity(100, activityCallback)
+
+ val job = underTest.cdmaLevel.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isEqualTo(2)
+
+ activityJob.cancel()
+ job.cancel()
+ }
+
+ private fun flipActivity(
+ times: Int,
+ callback: DataActivityListener,
+ ) {
+ repeat(times) { index -> callback.onDataActivity(index % 4) }
+ }
+
+ private fun flipDisplayInfo(
+ times: Int,
+ infos: List<TelephonyDisplayInfo>,
+ callback: DisplayInfoListener,
+ ) {
+ val len = infos.size
+ repeat(times) { index -> callback.onDisplayInfoChanged(infos[index % len]) }
+ }
+
+ private inline fun <reified T> getTelephonyCallbackForType(): T {
+ return getTelephonyCallbackForType(telephonyManager)
+ }
+
+ companion object {
+ private const val SUB_1_ID = 1
+
+ private val DEFAULT_NAME = NetworkNameModel.Default("default name")
+ private const val SEP = "-"
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
index 09b7a66c925d..68b1cda62f4c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
@@ -37,12 +37,12 @@ import com.android.settingslib.mobile.MobileMappings
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.tableBufferLogName
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.kt
index 621f79307e49..d07b96f6609e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.kt
@@ -16,10 +16,14 @@
package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
+import android.telephony.CellSignalStrengthCdma
+import android.telephony.SignalStrength
import android.telephony.TelephonyCallback
import android.telephony.TelephonyManager
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.mockito.Mockito.verify
@@ -31,6 +35,19 @@ object MobileTelephonyHelpers {
return callbackCaptor.allValues
}
+ /** Convenience constructor for SignalStrength */
+ fun signalStrength(gsmLevel: Int, cdmaLevel: Int, isGsm: Boolean): SignalStrength {
+ val signalStrength = mock<SignalStrength>()
+ whenever(signalStrength.isGsm).thenReturn(isGsm)
+ whenever(signalStrength.level).thenReturn(gsmLevel)
+ val cdmaStrength =
+ mock<CellSignalStrengthCdma>().also { whenever(it.level).thenReturn(cdmaLevel) }
+ whenever(signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java))
+ .thenReturn(listOf(cdmaStrength))
+
+ return signalStrength
+ }
+
inline fun <reified T> getTelephonyCallbackForType(mockTelephonyManager: TelephonyManager): T {
val cbs = getTelephonyCallbacks(mockTelephonyManager).filterIsInstance<T>()
assertThat(cbs.size).isEqualTo(1)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
index fa072fc366eb..1eb1056204cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
@@ -23,7 +23,6 @@ import com.android.settingslib.SignalIcon.MobileIconGroup
import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.CarrierMergedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
@@ -74,9 +73,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
@Test
fun gsm_level_default_unknown() =
runBlocking(IMMEDIATE) {
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(isGsm = true),
- )
+ connectionRepository.isGsm.value = true
var latest: Int? = null
val job = underTest.level.onEach { latest = it }.launchIn(this)
@@ -89,13 +86,9 @@ class MobileIconInteractorTest : SysuiTestCase() {
@Test
fun gsm_usesGsmLevel() =
runBlocking(IMMEDIATE) {
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- isGsm = true,
- primaryLevel = GSM_LEVEL,
- cdmaLevel = CDMA_LEVEL
- ),
- )
+ connectionRepository.isGsm.value = true
+ connectionRepository.primaryLevel.value = GSM_LEVEL
+ connectionRepository.cdmaLevel.value = CDMA_LEVEL
var latest: Int? = null
val job = underTest.level.onEach { latest = it }.launchIn(this)
@@ -108,13 +101,9 @@ class MobileIconInteractorTest : SysuiTestCase() {
@Test
fun gsm_alwaysShowCdmaTrue_stillUsesGsmLevel() =
runBlocking(IMMEDIATE) {
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- isGsm = true,
- primaryLevel = GSM_LEVEL,
- cdmaLevel = CDMA_LEVEL,
- ),
- )
+ connectionRepository.isGsm.value = true
+ connectionRepository.primaryLevel.value = GSM_LEVEL
+ connectionRepository.cdmaLevel.value = CDMA_LEVEL
mobileIconsInteractor.alwaysUseCdmaLevel.value = true
var latest: Int? = null
@@ -128,9 +117,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
@Test
fun notGsm_level_default_unknown() =
runBlocking(IMMEDIATE) {
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(isGsm = false),
- )
+ connectionRepository.isGsm.value = false
var latest: Int? = null
val job = underTest.level.onEach { latest = it }.launchIn(this)
@@ -142,13 +129,9 @@ class MobileIconInteractorTest : SysuiTestCase() {
@Test
fun notGsm_alwaysShowCdmaTrue_usesCdmaLevel() =
runBlocking(IMMEDIATE) {
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- isGsm = false,
- primaryLevel = GSM_LEVEL,
- cdmaLevel = CDMA_LEVEL
- ),
- )
+ connectionRepository.isGsm.value = false
+ connectionRepository.primaryLevel.value = GSM_LEVEL
+ connectionRepository.cdmaLevel.value = CDMA_LEVEL
mobileIconsInteractor.alwaysUseCdmaLevel.value = true
var latest: Int? = null
@@ -162,13 +145,9 @@ class MobileIconInteractorTest : SysuiTestCase() {
@Test
fun notGsm_alwaysShowCdmaFalse_usesPrimaryLevel() =
runBlocking(IMMEDIATE) {
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- isGsm = false,
- primaryLevel = GSM_LEVEL,
- cdmaLevel = CDMA_LEVEL,
- ),
- )
+ connectionRepository.isGsm.value = false
+ connectionRepository.primaryLevel.value = GSM_LEVEL
+ connectionRepository.cdmaLevel.value = CDMA_LEVEL
mobileIconsInteractor.alwaysUseCdmaLevel.value = false
var latest: Int? = null
@@ -197,11 +176,8 @@ class MobileIconInteractorTest : SysuiTestCase() {
@Test
fun iconGroup_three_g() =
runBlocking(IMMEDIATE) {
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
- ),
- )
+ connectionRepository.resolvedNetworkType.value =
+ DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
var latest: MobileIconGroup? = null
val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -214,23 +190,14 @@ class MobileIconInteractorTest : SysuiTestCase() {
@Test
fun iconGroup_updates_on_change() =
runBlocking(IMMEDIATE) {
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
- ),
- )
+ connectionRepository.resolvedNetworkType.value =
+ DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
var latest: MobileIconGroup? = null
val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- resolvedNetworkType =
- DefaultNetworkType(
- mobileMappingsProxy.toIconKey(FOUR_G),
- ),
- ),
- )
+ connectionRepository.resolvedNetworkType.value =
+ DefaultNetworkType(mobileMappingsProxy.toIconKey(FOUR_G))
yield()
assertThat(latest).isEqualTo(TelephonyIcons.FOUR_G)
@@ -241,12 +208,8 @@ class MobileIconInteractorTest : SysuiTestCase() {
@Test
fun iconGroup_5g_override_type() =
runBlocking(IMMEDIATE) {
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- resolvedNetworkType =
- OverrideNetworkType(mobileMappingsProxy.toIconKeyOverride(FIVE_G_OVERRIDE))
- ),
- )
+ connectionRepository.resolvedNetworkType.value =
+ OverrideNetworkType(mobileMappingsProxy.toIconKeyOverride(FIVE_G_OVERRIDE))
var latest: MobileIconGroup? = null
val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -259,12 +222,8 @@ class MobileIconInteractorTest : SysuiTestCase() {
@Test
fun iconGroup_default_if_no_lookup() =
runBlocking(IMMEDIATE) {
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- resolvedNetworkType =
- DefaultNetworkType(mobileMappingsProxy.toIconKey(NETWORK_TYPE_UNKNOWN)),
- ),
- )
+ connectionRepository.resolvedNetworkType.value =
+ DefaultNetworkType(mobileMappingsProxy.toIconKey(NETWORK_TYPE_UNKNOWN))
var latest: MobileIconGroup? = null
val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -277,11 +236,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
@Test
fun iconGroup_carrierMerged_usesOverride() =
runBlocking(IMMEDIATE) {
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- resolvedNetworkType = CarrierMergedNetworkType,
- ),
- )
+ connectionRepository.resolvedNetworkType.value = CarrierMergedNetworkType
var latest: MobileIconGroup? = null
val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -295,11 +250,8 @@ class MobileIconInteractorTest : SysuiTestCase() {
fun `icon group - checks default data`() =
runBlocking(IMMEDIATE) {
mobileIconsInteractor.defaultDataSubId.value = SUB_1_ID
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
- ),
- )
+ connectionRepository.resolvedNetworkType.value =
+ DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
var latest: MobileIconGroup? = null
val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -380,9 +332,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
var latest: Boolean? = null
val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this)
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(dataConnectionState = DataConnectionState.Connected)
- )
+ connectionRepository.dataConnectionState.value = DataConnectionState.Connected
yield()
assertThat(latest).isTrue()
@@ -396,9 +346,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
var latest: Boolean? = null
val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this)
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(dataConnectionState = DataConnectionState.Disconnected)
- )
+ connectionRepository.dataConnectionState.value = DataConnectionState.Disconnected
assertThat(latest).isFalse()
@@ -411,11 +359,11 @@ class MobileIconInteractorTest : SysuiTestCase() {
var latest: Boolean? = null
val job = underTest.isInService.onEach { latest = it }.launchIn(this)
- connectionRepository.setConnectionInfo(MobileConnectionModel(isInService = true))
+ connectionRepository.isInService.value = true
assertThat(latest).isTrue()
- connectionRepository.setConnectionInfo(MobileConnectionModel(isInService = false))
+ connectionRepository.isInService.value = false
assertThat(latest).isFalse()
@@ -429,22 +377,13 @@ class MobileIconInteractorTest : SysuiTestCase() {
val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
connectionRepository.cdmaRoaming.value = true
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- isGsm = true,
- isRoaming = false,
- )
- )
+ connectionRepository.isGsm.value = true
+ connectionRepository.isRoaming.value = false
yield()
assertThat(latest).isFalse()
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- isGsm = true,
- isRoaming = true,
- )
- )
+ connectionRepository.isRoaming.value = true
yield()
assertThat(latest).isTrue()
@@ -459,23 +398,15 @@ class MobileIconInteractorTest : SysuiTestCase() {
val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
connectionRepository.cdmaRoaming.value = false
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- isGsm = false,
- isRoaming = true,
- )
- )
+ connectionRepository.isGsm.value = false
+ connectionRepository.isRoaming.value = true
yield()
assertThat(latest).isFalse()
connectionRepository.cdmaRoaming.value = true
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- isGsm = false,
- isRoaming = false,
- )
- )
+ connectionRepository.isGsm.value = false
+ connectionRepository.isRoaming.value = false
yield()
assertThat(latest).isTrue()
@@ -490,25 +421,15 @@ class MobileIconInteractorTest : SysuiTestCase() {
val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
connectionRepository.cdmaRoaming.value = true
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- isGsm = false,
- isRoaming = true,
- carrierNetworkChangeActive = true,
- )
- )
+ connectionRepository.isGsm.value = false
+ connectionRepository.isRoaming.value = true
+ connectionRepository.carrierNetworkChangeActive.value = true
yield()
assertThat(latest).isFalse()
connectionRepository.cdmaRoaming.value = true
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(
- isGsm = true,
- isRoaming = true,
- carrierNetworkChangeActive = true,
- )
- )
+ connectionRepository.isGsm.value = true
yield()
assertThat(latest).isFalse()
@@ -526,24 +447,20 @@ class MobileIconInteractorTest : SysuiTestCase() {
// Default network name, operator name is non-null, uses the operator name
connectionRepository.networkName.value = DEFAULT_NAME
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(operatorAlphaShort = testOperatorName)
- )
+ connectionRepository.operatorAlphaShort.value = testOperatorName
yield()
assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived(testOperatorName))
// Default network name, operator name is null, uses the default
- connectionRepository.setConnectionInfo(MobileConnectionModel(operatorAlphaShort = null))
+ connectionRepository.operatorAlphaShort.value = null
yield()
assertThat(latest).isEqualTo(DEFAULT_NAME)
// Derived network name, operator name non-null, uses the derived name
connectionRepository.networkName.value = DERIVED_NAME
- connectionRepository.setConnectionInfo(
- MobileConnectionModel(operatorAlphaShort = testOperatorName)
- )
+ connectionRepository.operatorAlphaShort.value = testOperatorName
yield()
assertThat(latest).isEqualTo(DERIVED_NAME)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt
new file mode 100644
index 000000000000..4aa48d6f25f1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.ui
+
+import android.widget.TextView
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.log.LogBufferFactory
+import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger.Companion.getIdForLogging
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.KeyguardMobileIconViewModel
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.QsMobileIconViewModel
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import java.io.PrintWriter
+import java.io.StringWriter
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+class MobileViewLoggerTest : SysuiTestCase() {
+ private val buffer = LogBufferFactory(DumpManager(), mock()).create("buffer", 10)
+ private val stringWriter = StringWriter()
+ private val printWriter = PrintWriter(stringWriter)
+
+ private val underTest = MobileViewLogger(buffer, mock())
+
+ @Mock private lateinit var flags: StatusBarPipelineFlags
+ @Mock private lateinit var commonViewModel: MobileIconViewModel
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ }
+
+ @Test
+ fun collectionStarted_dumpHasInfo() {
+ val view = TextView(context)
+ val viewModel = QsMobileIconViewModel(commonViewModel, flags)
+
+ underTest.logCollectionStarted(view, viewModel)
+
+ val dumpString = getDumpString()
+ assertThat(dumpString).contains("${view.getIdForLogging()}, isCollecting=true")
+ }
+
+ @Test
+ fun collectionStarted_multipleViews_dumpHasInfo() {
+ val view = TextView(context)
+ val view2 = TextView(context)
+ val viewModel = QsMobileIconViewModel(commonViewModel, flags)
+ val viewModel2 = KeyguardMobileIconViewModel(commonViewModel, flags)
+
+ underTest.logCollectionStarted(view, viewModel)
+ underTest.logCollectionStarted(view2, viewModel2)
+
+ val dumpString = getDumpString()
+ assertThat(dumpString).contains("${view.getIdForLogging()}, isCollecting=true")
+ assertThat(dumpString).contains("${view2.getIdForLogging()}, isCollecting=true")
+ }
+
+ @Test
+ fun collectionStopped_dumpHasInfo() {
+ val view = TextView(context)
+ val view2 = TextView(context)
+ val viewModel = QsMobileIconViewModel(commonViewModel, flags)
+ val viewModel2 = KeyguardMobileIconViewModel(commonViewModel, flags)
+
+ underTest.logCollectionStarted(view, viewModel)
+ underTest.logCollectionStarted(view2, viewModel2)
+ underTest.logCollectionStopped(view, viewModel)
+
+ val dumpString = getDumpString()
+ assertThat(dumpString).contains("${view.getIdForLogging()}, isCollecting=false")
+ assertThat(dumpString).contains("${view2.getIdForLogging()}, isCollecting=true")
+ }
+
+ private fun getDumpString(): String {
+ underTest.dump(printWriter, args = arrayOf())
+ return stringWriter.toString()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
index e68a3970ae93..7420db2e895e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
@@ -32,6 +32,7 @@ import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.QsMobileIconViewModel
@@ -60,6 +61,7 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
@Mock private lateinit var tableLogBuffer: TableLogBuffer
+ @Mock private lateinit var viewLogger: MobileViewLogger
@Mock private lateinit var constants: ConnectivityConstants
private lateinit var interactor: FakeMobileIconInteractor
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
@@ -94,7 +96,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Test
fun setVisibleState_icon_iconShownDotHidden() {
- val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
+ val view =
+ ModernStatusBarMobileView.constructAndBind(
+ context,
+ viewLogger,
+ SLOT_NAME,
+ viewModel,
+ )
view.setVisibleState(StatusBarIconView.STATE_ICON, /* animate= */ false)
@@ -109,8 +117,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Test
fun setVisibleState_dot_iconHiddenDotShown() {
- val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+ val view =
+ ModernStatusBarMobileView.constructAndBind(
+ context,
+ viewLogger,
+ SLOT_NAME,
+ viewModel,
+ )
view.setVisibleState(StatusBarIconView.STATE_DOT, /* animate= */ false)
ViewUtils.attachView(view)
@@ -124,8 +137,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Test
fun setVisibleState_hidden_iconAndDotHidden() {
- val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+ val view =
+ ModernStatusBarMobileView.constructAndBind(
+ context,
+ viewLogger,
+ SLOT_NAME,
+ viewModel,
+ )
view.setVisibleState(StatusBarIconView.STATE_HIDDEN, /* animate= */ false)
ViewUtils.attachView(view)
@@ -142,8 +160,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
whenever(constants.hasDataCapabilities).thenReturn(false)
createViewModel()
- val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+ val view =
+ ModernStatusBarMobileView.constructAndBind(
+ context,
+ viewLogger,
+ SLOT_NAME,
+ viewModel,
+ )
ViewUtils.attachView(view)
testableLooper.processAllMessages()
@@ -157,8 +180,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
whenever(constants.hasDataCapabilities).thenReturn(true)
createViewModel()
- val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+ val view =
+ ModernStatusBarMobileView.constructAndBind(
+ context,
+ viewLogger,
+ SLOT_NAME,
+ viewModel,
+ )
ViewUtils.attachView(view)
testableLooper.processAllMessages()
@@ -171,8 +199,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
fun isIconVisible_notAirplaneMode_outputsTrue() {
airplaneModeRepository.setIsAirplaneMode(false)
- val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+ val view =
+ ModernStatusBarMobileView.constructAndBind(
+ context,
+ viewLogger,
+ SLOT_NAME,
+ viewModel,
+ )
ViewUtils.attachView(view)
testableLooper.processAllMessages()
@@ -185,8 +218,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
fun isIconVisible_airplaneMode_outputsTrue() {
airplaneModeRepository.setIsAirplaneMode(true)
- val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+ val view =
+ ModernStatusBarMobileView.constructAndBind(
+ context,
+ viewLogger,
+ SLOT_NAME,
+ viewModel,
+ )
ViewUtils.attachView(view)
testableLooper.processAllMessages()
@@ -198,7 +236,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Test
fun onDarkChanged_iconHasNewColor() {
whenever(statusBarPipelineFlags.useDebugColoring()).thenReturn(false)
- val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
+ val view =
+ ModernStatusBarMobileView.constructAndBind(
+ context,
+ viewLogger,
+ SLOT_NAME,
+ viewModel,
+ )
ViewUtils.attachView(view)
testableLooper.processAllMessages()
@@ -214,7 +258,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Test
fun setStaticDrawableColor_iconHasNewColor() {
whenever(statusBarPipelineFlags.useDebugColoring()).thenReturn(false)
- val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
+ val view =
+ ModernStatusBarMobileView.constructAndBind(
+ context,
+ viewLogger,
+ SLOT_NAME,
+ viewModel,
+ )
ViewUtils.attachView(view)
testableLooper.processAllMessages()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
index f9830309252d..a6d915243f60 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
@@ -28,6 +28,7 @@ import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModelTest.Companion.defaultSignal
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
@@ -84,7 +85,7 @@ class LocationBasedMobileIconViewModelTest : SysuiTestCase() {
testScope.backgroundScope,
)
- homeIcon = HomeMobileIconViewModel(commonImpl, statusBarPipelineFlags)
+ homeIcon = HomeMobileIconViewModel(commonImpl, statusBarPipelineFlags, mock())
qsIcon = QsMobileIconViewModel(commonImpl, statusBarPipelineFlags)
keyguardIcon = KeyguardMobileIconViewModel(commonImpl, statusBarPipelineFlags)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
index 4628f8410245..ddb7f4d88d30 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
@@ -24,6 +24,8 @@ import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirp
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
+import com.android.systemui.statusbar.pipeline.mobile.ui.VerboseMobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
@@ -51,6 +53,8 @@ class MobileIconsViewModelTest : SysuiTestCase() {
private lateinit var airplaneModeInteractor: AirplaneModeInteractor
@Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
@Mock private lateinit var constants: ConnectivityConstants
+ @Mock private lateinit var logger: MobileViewLogger
+ @Mock private lateinit var verboseLogger: VerboseMobileViewLogger
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
@@ -73,6 +77,8 @@ class MobileIconsViewModelTest : SysuiTestCase() {
underTest =
MobileIconsViewModel(
subscriptionIdsFlow,
+ logger,
+ verboseLogger,
interactor,
airplaneModeInteractor,
constants,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
index e4c8fd0cd8a1..b4039d906810 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
@@ -164,6 +164,10 @@ class ModernStatusBarViewTest : SysuiTestCase() {
override fun getShouldIconBeVisible(): Boolean {
return shouldIconBeVisibleInternal
}
+
+ override fun isCollecting(): Boolean {
+ return true
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
index 12b16640c0c2..1c71f8ba0aa3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
@@ -368,40 +368,37 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase
// network = CarrierMerged => not shown
TestCase(
+ enabled = true,
+ isDefault = true,
+ forceHidden = false,
network =
WifiNetworkModel.CarrierMerged(NETWORK_ID, subscriptionId = 1, level = 1),
expected = null,
),
- // network = Inactive => not shown
+ // isDefault = false => no networks shown
TestCase(
+ isDefault = false,
network = WifiNetworkModel.Inactive,
expected = null,
),
-
- // network = Unavailable => not shown
TestCase(
+ isDefault = false,
network = WifiNetworkModel.Unavailable,
expected = null,
),
-
- // network = Active & validated = false => not shown
TestCase(
+ isDefault = false,
network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 3),
expected = null,
),
- // network = Active & validated = true => shown
+ // Even though this network is active and validated, we still doesn't want it shown
+ // because wifi isn't the default connection (b/272509965).
TestCase(
+ isDefault = false,
network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 4),
- expected =
- Expected(
- iconResource = WIFI_FULL_ICONS[4],
- contentDescription = { context ->
- context.getString(WIFI_CONNECTION_STRENGTH[4])
- },
- description = "Full internet level 4 icon",
- ),
+ expected = null,
),
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
index 5129f8584165..6980a0b4565e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
@@ -90,6 +90,12 @@ class DeviceProvisionedControllerImplTest : SysuiTestCase() {
}
@Test
+ fun testFrpNotActiveByDefault() {
+ init()
+ assertThat(controller.isFrpActive).isFalse()
+ }
+
+ @Test
fun testNotUserSetupByDefault() {
init()
assertThat(controller.isUserSetup(START_USER)).isFalse()
@@ -104,6 +110,14 @@ class DeviceProvisionedControllerImplTest : SysuiTestCase() {
}
@Test
+ fun testFrpActiveWhenCreated() {
+ settings.putInt(Settings.Secure.SECURE_FRP_MODE, 1)
+ init()
+
+ assertThat(controller.isFrpActive).isTrue()
+ }
+
+ @Test
fun testUserSetupWhenCreated() {
settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
init()
@@ -122,6 +136,16 @@ class DeviceProvisionedControllerImplTest : SysuiTestCase() {
}
@Test
+ fun testFrpActiveChange() {
+ init()
+
+ settings.putInt(Settings.Secure.SECURE_FRP_MODE, 1)
+ testableLooper.processAllMessages() // background observer
+
+ assertThat(controller.isFrpActive).isTrue()
+ }
+
+ @Test
fun testUserSetupChange() {
init()
@@ -164,6 +188,7 @@ class DeviceProvisionedControllerImplTest : SysuiTestCase() {
mainExecutor.runAllReady()
verify(listener, never()).onDeviceProvisionedChanged()
+ verify(listener, never()).onFrpActiveChanged()
verify(listener, never()).onUserSetupChanged()
verify(listener, never()).onUserSwitched()
}
@@ -181,6 +206,7 @@ class DeviceProvisionedControllerImplTest : SysuiTestCase() {
verify(listener).onUserSwitched()
verify(listener, never()).onUserSetupChanged()
verify(listener, never()).onDeviceProvisionedChanged()
+ verify(listener, never()).onFrpActiveChanged()
}
@Test
@@ -195,6 +221,7 @@ class DeviceProvisionedControllerImplTest : SysuiTestCase() {
verify(listener, never()).onUserSwitched()
verify(listener).onUserSetupChanged()
verify(listener, never()).onDeviceProvisionedChanged()
+ verify(listener, never()).onFrpActiveChanged()
}
@Test
@@ -208,10 +235,26 @@ class DeviceProvisionedControllerImplTest : SysuiTestCase() {
verify(listener, never()).onUserSwitched()
verify(listener, never()).onUserSetupChanged()
+ verify(listener, never()).onFrpActiveChanged()
verify(listener).onDeviceProvisionedChanged()
}
@Test
+ fun testListenerCalledOnFrpActiveChanged() {
+ init()
+ controller.addCallback(listener)
+
+ settings.putInt(Settings.Secure.SECURE_FRP_MODE, 1)
+ testableLooper.processAllMessages()
+ mainExecutor.runAllReady()
+
+ verify(listener, never()).onUserSwitched()
+ verify(listener, never()).onUserSetupChanged()
+ verify(listener, never()).onDeviceProvisionedChanged()
+ verify(listener).onFrpActiveChanged()
+ }
+
+ @Test
fun testRemoveListener() {
init()
controller.addCallback(listener)
@@ -220,11 +263,13 @@ class DeviceProvisionedControllerImplTest : SysuiTestCase() {
switchUser(10)
settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
settings.putInt(Settings.Global.DEVICE_PROVISIONED, 1)
+ settings.putInt(Settings.Secure.SECURE_FRP_MODE, 1)
testableLooper.processAllMessages()
mainExecutor.runAllReady()
verify(listener, never()).onDeviceProvisionedChanged()
+ verify(listener, never()).onFrpActiveChanged()
verify(listener, never()).onUserSetupChanged()
verify(listener, never()).onUserSwitched()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
index 48b17322da4d..481d453fa0b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
@@ -38,6 +38,7 @@ import com.android.internal.R;
import com.android.internal.view.RotationPolicy;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.util.wrapper.RotationPolicyWrapper;
@@ -55,10 +56,12 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
private static final String[] DEFAULT_SETTINGS = new String[]{"0:1", "2:0:1", "1:2"};
+ @Mock private DeviceStateManager mDeviceStateManager;
+ @Mock private DeviceStateRotationLockSettingControllerLogger mLogger;
+ @Mock private DumpManager mDumpManager;
+
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private final FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock);
- @Mock
- private DeviceStateManager mDeviceStateManager;
private final RotationPolicyWrapper mFakeRotationPolicy = new FakeRotationPolicy();
private DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingController;
private DeviceStateManager.DeviceStateCallback mDeviceStateCallback;
@@ -78,7 +81,13 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
mSettingsManager = DeviceStateRotationLockSettingsManager.getInstance(mContext);
mDeviceStateRotationLockSettingController =
new DeviceStateRotationLockSettingController(
- mFakeRotationPolicy, mDeviceStateManager, mFakeExecutor, mSettingsManager);
+ mFakeRotationPolicy,
+ mDeviceStateManager,
+ mFakeExecutor,
+ mSettingsManager,
+ mLogger,
+ mDumpManager
+ );
mDeviceStateRotationLockSettingController.setListening(true);
verify(mDeviceStateManager)
@@ -173,15 +182,11 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
}
@Test
- public void whenDeviceStateSwitchedToIgnoredState_usePreviousSetting() {
- initializeSettingsWith(
- 0, DEVICE_STATE_ROTATION_LOCK_IGNORED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
- mFakeRotationPolicy.setRotationLock(true);
-
- mDeviceStateCallback.onStateChanged(1);
- assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();
-
+ public void whenDeviceStateSwitchedToIgnoredState_useFallbackSetting() {
mDeviceStateCallback.onStateChanged(0);
+ assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue();
+
+ mDeviceStateCallback.onStateChanged(2);
assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt
new file mode 100644
index 000000000000..89cc18cc5d67
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt
@@ -0,0 +1,121 @@
+/*
+ * 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.surfaceeffects.ripple
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class RippleShaderTest : SysuiTestCase() {
+
+ private lateinit var rippleShader: RippleShader
+
+ @Before
+ fun setup() {
+ rippleShader = RippleShader()
+ }
+
+ @Test
+ fun setMaxSize_hasCorrectSizes() {
+ val expectedMaxWidth = 300f
+ val expectedMaxHeight = 500f
+
+ rippleShader.rippleSize.setMaxSize(expectedMaxWidth, expectedMaxHeight)
+
+ assertThat(rippleShader.rippleSize.sizes.size).isEqualTo(2)
+ assertThat(rippleShader.rippleSize.sizes[0]).isEqualTo(rippleShader.rippleSize.initialSize)
+ val maxSize = rippleShader.rippleSize.sizes[1]
+ assertThat(maxSize.t).isEqualTo(1f)
+ assertThat(maxSize.width).isEqualTo(expectedMaxWidth)
+ assertThat(maxSize.height).isEqualTo(expectedMaxHeight)
+ }
+
+ @Test
+ fun setSizeAtProgresses_hasCorrectSizes() {
+ val expectedSize0 = RippleShader.SizeAtProgress(t = 0f, width = 100f, height = 100f)
+ val expectedSize1 = RippleShader.SizeAtProgress(t = 0.2f, width = 1500f, height = 1200f)
+ val expectedSize2 = RippleShader.SizeAtProgress(t = 0.4f, width = 200f, height = 70f)
+
+ rippleShader.rippleSize.setSizeAtProgresses(expectedSize0, expectedSize1, expectedSize2)
+
+ assertThat(rippleShader.rippleSize.sizes.size).isEqualTo(3)
+ assertThat(rippleShader.rippleSize.sizes[0]).isEqualTo(expectedSize0)
+ assertThat(rippleShader.rippleSize.sizes[1]).isEqualTo(expectedSize1)
+ assertThat(rippleShader.rippleSize.sizes[2]).isEqualTo(expectedSize2)
+ }
+
+ @Test
+ fun setSizeAtProgresses_sizeListIsSortedByT() {
+ val expectedSize0 = RippleShader.SizeAtProgress(t = 0f, width = 100f, height = 100f)
+ val expectedSize1 = RippleShader.SizeAtProgress(t = 0.2f, width = 1500f, height = 1200f)
+ val expectedSize2 = RippleShader.SizeAtProgress(t = 0.4f, width = 200f, height = 70f)
+ val expectedSize3 = RippleShader.SizeAtProgress(t = 0.8f, width = 300f, height = 900f)
+ val expectedSize4 = RippleShader.SizeAtProgress(t = 1f, width = 500f, height = 300f)
+
+ // Add them in unsorted order
+ rippleShader.rippleSize.setSizeAtProgresses(
+ expectedSize0,
+ expectedSize3,
+ expectedSize2,
+ expectedSize4,
+ expectedSize1
+ )
+
+ assertThat(rippleShader.rippleSize.sizes.size).isEqualTo(5)
+ assertThat(rippleShader.rippleSize.sizes[0]).isEqualTo(expectedSize0)
+ assertThat(rippleShader.rippleSize.sizes[1]).isEqualTo(expectedSize1)
+ assertThat(rippleShader.rippleSize.sizes[2]).isEqualTo(expectedSize2)
+ assertThat(rippleShader.rippleSize.sizes[3]).isEqualTo(expectedSize3)
+ assertThat(rippleShader.rippleSize.sizes[4]).isEqualTo(expectedSize4)
+ }
+
+ @Test
+ fun update_getsCorrectNextTargetSize() {
+ val expectedSize0 = RippleShader.SizeAtProgress(t = 0f, width = 100f, height = 100f)
+ val expectedSize1 = RippleShader.SizeAtProgress(t = 0.2f, width = 1500f, height = 1200f)
+ val expectedSize2 = RippleShader.SizeAtProgress(t = 0.4f, width = 200f, height = 70f)
+ val expectedSize3 = RippleShader.SizeAtProgress(t = 0.8f, width = 300f, height = 900f)
+ val expectedSize4 = RippleShader.SizeAtProgress(t = 1f, width = 500f, height = 300f)
+
+ rippleShader.rippleSize.setSizeAtProgresses(
+ expectedSize0,
+ expectedSize1,
+ expectedSize2,
+ expectedSize3,
+ expectedSize4
+ )
+
+ rippleShader.rippleSize.update(0.5f)
+ // Progress is between 0.4 and 0.8 (expectedSize3 and 4), so the index should be 3.
+ assertThat(rippleShader.rippleSize.currentSizeIndex).isEqualTo(3)
+ }
+
+ @Test
+ fun update_sizeListIsEmpty_setsInitialSize() {
+ assertThat(rippleShader.rippleSize.sizes).isEmpty()
+
+ rippleShader.rippleSize.update(0.3f)
+
+ assertThat(rippleShader.rippleSize.sizes.size).isEqualTo(1)
+ assertThat(rippleShader.rippleSize.sizes[0]).isEqualTo(rippleShader.rippleSize.initialSize)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
index 5288608a202d..0413d92b6abb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
@@ -25,7 +25,6 @@ import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
import com.android.systemui.unfold.util.TestFoldStateProvider
import org.junit.Before
import org.junit.Test
@@ -50,7 +49,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendHingeAngleUpdate(180f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
@@ -67,7 +66,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendHingeAngleUpdate(180f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
@@ -84,7 +83,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendHingeAngleUpdate(180f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
)
with(listener.ensureTransitionFinished()) {
@@ -113,7 +112,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
fun testUnfoldAndStopUnfolding_finishesTheUnfoldTransition() {
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN) },
@@ -129,7 +128,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
fun testFoldImmediatelyAfterUnfold_runsFoldAnimation() {
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
index 6086e16fb49a..8476d0d45603 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
@@ -26,6 +26,7 @@ import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.system.ActivityManagerActivityTypeProvider
import com.android.systemui.unfold.updates.FoldProvider.FoldCallback
import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListener
+import com.android.systemui.unfold.updates.hinge.FULLY_OPEN_DEGREES
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
@@ -71,6 +72,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
private val foldUpdates: MutableList<Int> = arrayListOf()
private val hingeAngleUpdates: MutableList<Float> = arrayListOf()
+ private val unfoldedScreenAvailabilityUpdates: MutableList<Unit> = arrayListOf()
private var scheduledRunnable: Runnable? = null
private var scheduledRunnableDelay: Long? = null
@@ -106,6 +108,10 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
override fun onFoldUpdate(update: Int) {
foldUpdates.add(update)
}
+
+ override fun onUnfoldedScreenAvailable() {
+ unfoldedScreenAvailabilityUpdates.add(Unit)
+ }
})
foldStateProvider.start()
@@ -156,8 +162,8 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
sendHingeAngleEvent(10)
screenOnStatusProvider.notifyScreenTurnedOn()
- assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING,
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE)
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING)
+ assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
}
@Test
@@ -174,8 +180,9 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
sendHingeAngleEvent(40)
sendHingeAngleEvent(10)
- assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING,
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE, FOLD_UPDATE_START_CLOSING)
+ assertThat(foldUpdates)
+ .containsExactly(FOLD_UPDATE_START_OPENING, FOLD_UPDATE_START_CLOSING)
+ assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
}
@Test
@@ -223,7 +230,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
fireScreenOnEvent()
- assertThat(foldUpdates).containsExactly(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE)
+ assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
}
@Test
@@ -277,7 +284,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_afterTimeout_finishHalfOpenEventEmitted() {
- sendHingeAngleEvent(90)
+ setInitialHingeAngle(90)
sendHingeAngleEvent(80)
simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS)
@@ -288,7 +295,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_beforeTimeout_abortNotEmitted() {
- sendHingeAngleEvent(90)
+ setInitialHingeAngle(90)
sendHingeAngleEvent(80)
simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS - 1)
@@ -298,7 +305,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_eventBeforeTimeout_oneEventEmitted() {
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(90)
simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS - 1)
@@ -309,7 +316,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_timeoutAfterTimeoutRescheduled_finishHalfOpenStateEmitted() {
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(90)
// The timeout should not trigger here.
@@ -323,7 +330,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_shortTimeBetween_emitsOnlyOneEvents() {
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(90)
sendHingeAngleEvent(80)
@@ -334,20 +341,19 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileClosing_emittedDespiteInitialAngle() {
val maxAngle = 180 - FULLY_OPEN_THRESHOLD_DEGREES.toInt()
- for (i in 1..maxAngle) {
- foldUpdates.clear()
-
- simulateFolding(startAngle = i)
+ val minAngle = Math.ceil(HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toDouble()).toInt() + 1
+ for (startAngle in minAngle..maxAngle) {
+ setInitialHingeAngle(startAngle)
+ sendHingeAngleEvent(startAngle - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
- simulateTimeout() // Timeout to set the state to aborted.
}
}
@Test
fun startClosingEvent_whileNotOnLauncher_doesNotTriggerBeforeThreshold() {
setupForegroundActivityType(isHomeActivity = false)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -357,7 +363,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileActivityTypeNotAvailable_triggerBeforeThreshold() {
setupForegroundActivityType(isHomeActivity = null)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -367,7 +373,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileOnLauncher_doesTriggerBeforeThreshold() {
setupForegroundActivityType(isHomeActivity = true)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -377,9 +383,11 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileNotOnLauncher_triggersAfterThreshold() {
setupForegroundActivityType(isHomeActivity = false)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
+ setInitialHingeAngle(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
+ sendHingeAngleEvent(
+ START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
+ HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
}
@@ -388,7 +396,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
fun startClosingEvent_whileNotOnKeyguardAndNotOnLauncher_doesNotTriggerBeforeThreshold() {
setKeyguardVisibility(visible = false)
setupForegroundActivityType(isHomeActivity = false)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -398,7 +406,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileKeyguardStateNotAvailable_triggerBeforeThreshold() {
setKeyguardVisibility(visible = null)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -408,7 +416,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileonKeyguard_doesTriggerBeforeThreshold() {
setKeyguardVisibility(visible = true)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -418,9 +426,59 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileNotOnKeyguard_triggersAfterThreshold() {
setKeyguardVisibility(visible = false)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
+ setInitialHingeAngle(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
+ sendHingeAngleEvent(
+ START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
+ HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
+
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startClosingEvent_doesNotTriggerBelowThreshold() {
+ val thresholdAngle = (FULLY_OPEN_DEGREES - FULLY_OPEN_THRESHOLD_DEGREES).toInt()
+ setInitialHingeAngle(180)
+ sendHingeAngleEvent(thresholdAngle + 1)
+
+ assertThat(foldUpdates).isEmpty()
+ }
+
+ @Test
+ fun startClosingEvent_triggersAfterThreshold() {
+ val thresholdAngle = (FULLY_OPEN_DEGREES - FULLY_OPEN_THRESHOLD_DEGREES).toInt()
+ setInitialHingeAngle(180)
+ sendHingeAngleEvent(thresholdAngle + 1)
+ sendHingeAngleEvent(thresholdAngle - 1)
+
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startClosingEvent_triggersAfterThreshold_fromHalfOpen() {
+ setInitialHingeAngle(120)
+ sendHingeAngleEvent((120 - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES + 1).toInt())
+ assertThat(foldUpdates).isEmpty()
+ sendHingeAngleEvent((120 - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES - 1).toInt())
+
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startOpeningAndClosingEvents_triggerWithOpenAndClose() {
+ setInitialHingeAngle(120)
+ sendHingeAngleEvent(130)
+ sendHingeAngleEvent(120)
+ assertThat(foldUpdates)
+ .containsExactly(FOLD_UPDATE_START_OPENING, FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startClosingEvent_notInterrupted_whenAngleIsSlightlyIncreased() {
+ setInitialHingeAngle(120)
+ sendHingeAngleEvent(110)
+ sendHingeAngleEvent(111)
+ sendHingeAngleEvent(100)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
}
@@ -504,11 +562,6 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
}
}
- private fun simulateFolding(startAngle: Int) {
- sendHingeAngleEvent(startAngle)
- sendHingeAngleEvent(startAngle - 1)
- }
-
private fun setFoldState(folded: Boolean) {
foldProvider.notifyFolded(folded)
}
@@ -521,6 +574,17 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
testHingeAngleProvider.notifyAngle(angle.toFloat())
}
+ private fun setInitialHingeAngle(angle: Int) {
+ setFoldState(angle == 0)
+ sendHingeAngleEvent(angle)
+ if (scheduledRunnableDelay != null) {
+ simulateTimeout()
+ }
+ hingeAngleUpdates.clear()
+ foldUpdates.clear()
+ unfoldedScreenAvailabilityUpdates.clear()
+ }
+
private class TestFoldProvider : FoldProvider {
private val callbacks = arrayListOf<FoldCallback>()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt
index 85cfef727954..fd368eb07b5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt
@@ -16,22 +16,24 @@
package com.android.systemui.unfold.updates
+import android.content.Context
+import android.hardware.display.DisplayManager
+import android.os.Looper
import android.testing.AndroidTestingRunner
-import android.view.IRotationWatcher
-import android.view.IWindowManager
+import android.view.Display
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListener
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.utils.os.FakeHandler
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Captor
import org.mockito.Mock
+import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.MockitoAnnotations
@@ -42,19 +44,23 @@ class RotationChangeProviderTest : SysuiTestCase() {
private lateinit var rotationChangeProvider: RotationChangeProvider
- @Mock lateinit var windowManagerInterface: IWindowManager
+ @Mock lateinit var displayManager: DisplayManager
@Mock lateinit var listener: RotationListener
- @Captor lateinit var rotationWatcher: ArgumentCaptor<IRotationWatcher>
- private val fakeExecutor = FakeExecutor(FakeSystemClock())
+ @Mock lateinit var display: Display
+ @Captor lateinit var displayListener: ArgumentCaptor<DisplayManager.DisplayListener>
+ private val fakeHandler = FakeHandler(Looper.getMainLooper())
+
+ private lateinit var spyContext: Context
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- rotationChangeProvider =
- RotationChangeProvider(windowManagerInterface, context, fakeExecutor)
+ spyContext = spy(context)
+ whenever(spyContext.display).thenReturn(display)
+ rotationChangeProvider = RotationChangeProvider(displayManager, spyContext, fakeHandler)
rotationChangeProvider.addCallback(listener)
- fakeExecutor.runAllReady()
- verify(windowManagerInterface).watchRotation(rotationWatcher.capture(), anyInt())
+ fakeHandler.dispatchQueuedMessages()
+ verify(displayManager).registerDisplayListener(displayListener.capture(), any())
}
@Test
@@ -70,15 +76,16 @@ class RotationChangeProviderTest : SysuiTestCase() {
verify(listener).onRotationChanged(42)
rotationChangeProvider.removeCallback(listener)
- fakeExecutor.runAllReady()
+ fakeHandler.dispatchQueuedMessages()
sendRotationUpdate(43)
- verify(windowManagerInterface).removeRotationWatcher(any())
+ verify(displayManager).unregisterDisplayListener(any())
verifyNoMoreInteractions(listener)
}
private fun sendRotationUpdate(newRotation: Int) {
- rotationWatcher.value.onRotationChanged(newRotation)
- fakeExecutor.runAllReady()
+ whenever(display.rotation).thenReturn(newRotation)
+ displayListener.allValues.forEach { it.onDisplayChanged(display.displayId) }
+ fakeHandler.dispatchQueuedMessages()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
index a064e8c81076..fbb0e5a72cd1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
@@ -57,4 +57,8 @@ class TestFoldStateProvider : FoldStateProvider {
fun sendHingeAngleUpdate(angle: Float) {
listeners.forEach { it.onHingeAngleUpdate(angle) }
}
+
+ fun sendUnfoldedScreenAvailable() {
+ listeners.forEach { it.onUnfoldedScreenAvailable() }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
index ccf378a71abd..ddd880b8037c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
@@ -17,10 +17,7 @@
package com.android.systemui.user.data.repository
-import android.app.IActivityManager
-import android.app.UserSwitchObserver
import android.content.pm.UserInfo
-import android.os.IRemoteCallback
import android.os.UserHandle
import android.os.UserManager
import android.provider.Settings
@@ -44,14 +41,8 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
-import org.mockito.ArgumentCaptor
-import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito.any
-import org.mockito.Mockito.anyString
import org.mockito.Mockito.mock
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@@ -60,8 +51,6 @@ import org.mockito.MockitoAnnotations
class UserRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var manager: UserManager
- @Mock private lateinit var activityManager: IActivityManager
- @Captor private lateinit var userSwitchObserver: ArgumentCaptor<UserSwitchObserver>
private lateinit var underTest: UserRepositoryImpl
@@ -229,30 +218,31 @@ class UserRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun userSwitchingInProgress_registersOnlyOneUserSwitchObserver() = runSelfCancelingTest {
+ fun userSwitchingInProgress_registersUserTrackerCallback() = runSelfCancelingTest {
underTest = create(this)
underTest.userSwitchingInProgress.launchIn(this)
underTest.userSwitchingInProgress.launchIn(this)
underTest.userSwitchingInProgress.launchIn(this)
- verify(activityManager, times(1)).registerUserSwitchObserver(any(), anyString())
+ // Two callbacks registered - one for observing user switching and one for observing the
+ // selected user
+ assertThat(tracker.callbacks.size).isEqualTo(2)
}
@Test
- fun userSwitchingInProgress_propagatesStateFromActivityManager() = runSelfCancelingTest {
+ fun userSwitchingInProgress_propagatesStateFromUserTracker() = runSelfCancelingTest {
underTest = create(this)
- verify(activityManager)
- .registerUserSwitchObserver(userSwitchObserver.capture(), anyString())
+ assertThat(tracker.callbacks.size).isEqualTo(2)
- userSwitchObserver.value.onUserSwitching(0, mock(IRemoteCallback::class.java))
+ tracker.onUserChanging(0)
var mostRecentSwitchingValue = false
underTest.userSwitchingInProgress.onEach { mostRecentSwitchingValue = it }.launchIn(this)
assertThat(mostRecentSwitchingValue).isTrue()
- userSwitchObserver.value.onUserSwitchComplete(0)
+ tracker.onUserChanged(0)
assertThat(mostRecentSwitchingValue).isFalse()
}
@@ -332,7 +322,6 @@ class UserRepositoryImplTest : SysuiTestCase() {
backgroundDispatcher = IMMEDIATE,
globalSettings = globalSettings,
tracker = tracker,
- activityManager = activityManager,
featureFlags = featureFlags,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
index d00acb89d228..3ed6cc88826c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
@@ -29,6 +29,8 @@ import android.os.UserManager
import android.provider.Settings
import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.GuestResetOrExitSessionReceiver
import com.android.systemui.GuestResumeSessionReceiver
import com.android.systemui.R
@@ -62,6 +64,7 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
+import junit.framework.Assert.assertNotNull
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.StandardTestDispatcher
@@ -72,6 +75,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
@@ -96,6 +100,7 @@ class UserInteractorTest : SysuiTestCase() {
@Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
@Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
@Mock private lateinit var commandQueue: CommandQueue
+ @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private lateinit var underTest: UserInteractor
@@ -154,6 +159,7 @@ class UserInteractorTest : SysuiTestCase() {
repository = telephonyRepository,
),
broadcastDispatcher = fakeBroadcastDispatcher,
+ keyguardUpdateMonitor = keyguardUpdateMonitor,
backgroundDispatcher = testDispatcher,
activityManager = activityManager,
refreshUsersScheduler = refreshUsersScheduler,
@@ -177,6 +183,18 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
+ fun `testKeyguardUpdateMonitor_onKeyguardGoingAway`() =
+ testScope.runTest {
+ val argumentCaptor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
+ verify(keyguardUpdateMonitor).registerCallback(argumentCaptor.capture())
+
+ argumentCaptor.value.onKeyguardGoingAway()
+
+ val lastValue = collectLastValue(underTest.dialogDismissRequests)
+ assertNotNull(lastValue)
+ }
+
+ @Test
fun `onRecordSelected - user`() =
testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
index 22fc32af1b80..daa71b942a2e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
@@ -25,6 +25,7 @@ import android.graphics.drawable.BitmapDrawable
import android.os.UserManager
import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.GuestResetOrExitSessionReceiver
import com.android.systemui.GuestResumeSessionReceiver
import com.android.systemui.SysuiTestCase
@@ -80,6 +81,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
@Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
@Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
@Mock private lateinit var commandQueue: CommandQueue
+ @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private lateinit var underTest: StatusBarUserChipViewModel
@@ -263,6 +265,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
repository = FakeTelephonyRepository(),
),
broadcastDispatcher = fakeBroadcastDispatcher,
+ keyguardUpdateMonitor = keyguardUpdateMonitor,
backgroundDispatcher = testDispatcher,
activityManager = activityManager,
refreshUsersScheduler = refreshUsersScheduler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index a2bd8d365192..e08ebf4a9050 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -23,6 +23,7 @@ import android.content.pm.UserInfo
import android.os.UserManager
import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.GuestResetOrExitSessionReceiver
import com.android.systemui.GuestResumeSessionReceiver
import com.android.systemui.SysuiTestCase
@@ -81,6 +82,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
@Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
@Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
@Mock private lateinit var commandQueue: CommandQueue
+ @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private lateinit var underTest: UserSwitcherViewModel
@@ -165,6 +167,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
repository = FakeTelephonyRepository(),
),
broadcastDispatcher = fakeBroadcastDispatcher,
+ keyguardUpdateMonitor = keyguardUpdateMonitor,
backgroundDispatcher = testDispatcher,
activityManager = activityManager,
refreshUsersScheduler = refreshUsersScheduler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java
index 046ad1293521..f9bfafc13f35 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.util.service;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
@@ -169,4 +171,19 @@ public class ObservableServiceConnectionTest extends SysuiTestCase {
verify(mCallback).onDisconnected(eq(connection),
eq(ObservableServiceConnection.DISCONNECT_REASON_UNBIND));
}
+
+ @Test
+ public void testBindServiceThrowsError() {
+ ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
+ mIntent, mExecutor, mTransformer);
+ connection.addCallback(mCallback);
+
+ when(mContext.bindService(eq(mIntent), anyInt(), eq(mExecutor), eq(connection)))
+ .thenThrow(new SecurityException());
+
+ // Verify that the exception was caught and that bind returns false, and we properly
+ // unbind.
+ assertThat(connection.bind()).isFalse();
+ verify(mContext).unbindService(connection);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
index 31cce4f3168b..468c5a73645b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
@@ -88,7 +88,7 @@ public class ImageWallpaperTest extends SysuiTestCase {
@Mock
private Bitmap mWallpaperBitmap;
FakeSystemClock mFakeSystemClock = new FakeSystemClock();
- FakeExecutor mFakeBackgroundExecutor = new FakeExecutor(mFakeSystemClock);
+ FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock);
@Before
public void setUp() throws Exception {
@@ -125,7 +125,7 @@ public class ImageWallpaperTest extends SysuiTestCase {
@Test
public void testBitmapWallpaper_normal() {
- // Will use a image wallpaper with dimensions DISPLAY_WIDTH x DISPLAY_WIDTH.
+ // Will use an image wallpaper with dimensions DISPLAY_WIDTH x DISPLAY_WIDTH.
// Then we expect the surface size will be also DISPLAY_WIDTH x DISPLAY_WIDTH.
int bitmapSide = DISPLAY_WIDTH;
testSurfaceHelper(
@@ -137,7 +137,7 @@ public class ImageWallpaperTest extends SysuiTestCase {
@Test
public void testBitmapWallpaper_low_resolution() {
- // Will use a image wallpaper with dimensions BMP_WIDTH x BMP_HEIGHT.
+ // Will use an image wallpaper with dimensions BMP_WIDTH x BMP_HEIGHT.
// Then we expect the surface size will be also BMP_WIDTH x BMP_HEIGHT.
testSurfaceHelper(LOW_BMP_WIDTH /* bitmapWidth */,
LOW_BMP_HEIGHT /* bitmapHeight */,
@@ -161,13 +161,13 @@ public class ImageWallpaperTest extends SysuiTestCase {
ImageWallpaper.CanvasEngine spyEngine = getSpyEngine();
spyEngine.onCreate(mSurfaceHolder);
spyEngine.onSurfaceRedrawNeeded(mSurfaceHolder);
- assertThat(mFakeBackgroundExecutor.numPending()).isAtLeast(1);
+ assertThat(mFakeExecutor.numPending()).isAtLeast(1);
int n = 0;
- while (mFakeBackgroundExecutor.numPending() >= 1) {
+ while (mFakeExecutor.numPending() >= 1) {
n++;
assertThat(n).isAtMost(10);
- mFakeBackgroundExecutor.runNextReady();
+ mFakeExecutor.runNextReady();
mFakeSystemClock.advanceTime(1000);
}
@@ -176,7 +176,7 @@ public class ImageWallpaperTest extends SysuiTestCase {
}
private ImageWallpaper createImageWallpaper() {
- return new ImageWallpaper(mFakeBackgroundExecutor, mUserTracker) {
+ return new ImageWallpaper(mFakeExecutor, mUserTracker) {
@Override
public Engine onCreateEngine() {
return new CanvasEngine() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
index 9b4f4969f9e9..c2947b42f56d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
@@ -29,6 +29,7 @@ import kotlinx.coroutines.test.runCurrent
/**
* Collect [flow] in a new [Job] and return a getter for the last collected value.
+ *
* ```
* fun myTest() = runTest {
* // ...
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeKeyboardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeKeyboardRepository.kt
new file mode 100644
index 000000000000..4e435462be50
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeKeyboardRepository.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyboard.data.repository
+
+import com.android.systemui.keyboard.shared.model.BacklightModel
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.filterNotNull
+
+class FakeKeyboardRepository : KeyboardRepository {
+
+ private val _keyboardConnected = MutableStateFlow(false)
+ override val keyboardConnected: Flow<Boolean> = _keyboardConnected
+
+ private val _backlightState: MutableStateFlow<BacklightModel?> = MutableStateFlow(null)
+ // filtering to make sure backlight doesn't have default initial value
+ override val backlight: Flow<BacklightModel> = _backlightState.filterNotNull()
+
+ fun setBacklight(state: BacklightModel) {
+ _backlightState.value = state
+ }
+
+ fun setKeyboardConnected(connected: Boolean) {
+ _keyboardConnected.value = connected
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
index 01dac362432d..d4b1701892c7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
@@ -21,6 +21,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.flowOf
class FakeBiometricSettingsRepository : BiometricSettingsRepository {
@@ -42,6 +43,9 @@ class FakeBiometricSettingsRepository : BiometricSettingsRepository {
override val isFingerprintEnabledByDevicePolicy =
_isFingerprintEnabledByDevicePolicy.asStateFlow()
+ override val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
+ get() = flowOf(true)
+
fun setFingerprintEnrolled(isFingerprintEnrolled: Boolean) {
_isFingerprintEnrolled.value = isFingerprintEnrolled
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt
new file mode 100644
index 000000000000..914c786a1c7f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.keyguard.data.repository
+
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class FakeDevicePostureRepository : DevicePostureRepository {
+ private val _currentDevicePosture = MutableStateFlow(DevicePosture.UNKNOWN)
+ override val currentDevicePosture: Flow<DevicePosture>
+ get() = _currentDevicePosture
+
+ fun setCurrentPosture(posture: DevicePosture) {
+ _currentDevicePosture.value = posture
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
index 337421974562..1dda47223dd6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
@@ -19,20 +19,16 @@ package com.android.systemui.keyguard.data.repository
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/** Fake implementation of [KeyguardRepository] */
class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
- private val _primaryBouncerVisible = MutableStateFlow(false)
- override val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow()
- private val _primaryBouncerShow = MutableStateFlow<KeyguardBouncerModel?>(null)
+ private val _primaryBouncerShow = MutableStateFlow(false)
override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
private val _primaryBouncerShowingSoon = MutableStateFlow(false)
override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
- private val _primaryBouncerHide = MutableStateFlow(false)
- override val primaryBouncerHide = _primaryBouncerHide.asStateFlow()
private val _primaryBouncerStartingToHide = MutableStateFlow(false)
override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
@@ -44,8 +40,6 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
private val _keyguardPosition = MutableStateFlow(0f)
override val keyguardPosition = _keyguardPosition.asStateFlow()
- private val _onScreenTurnedOff = MutableStateFlow(false)
- override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
@@ -61,15 +55,13 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
override var lastAlternateBouncerVisibleTime: Long = 0L
private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false)
override val alternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow()
+ private val _sideFpsShowing: MutableStateFlow<Boolean> = MutableStateFlow(false)
+ override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow()
override fun setPrimaryScrimmed(isScrimmed: Boolean) {
_primaryBouncerScrimmed.value = isScrimmed
}
- override fun setPrimaryVisible(isVisible: Boolean) {
- _primaryBouncerVisible.value = isVisible
- }
-
override fun setAlternateVisible(isVisible: Boolean) {
_isAlternateBouncerVisible.value = isVisible
}
@@ -78,18 +70,14 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
_isAlternateBouncerUIAvailable.value = isAvailable
}
- override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
- _primaryBouncerShow.value = keyguardBouncerModel
+ override fun setPrimaryShow(isShowing: Boolean) {
+ _primaryBouncerShow.value = isShowing
}
override fun setPrimaryShowingSoon(showingSoon: Boolean) {
_primaryBouncerShowingSoon.value = showingSoon
}
- override fun setPrimaryHide(hide: Boolean) {
- _primaryBouncerHide.value = hide
- }
-
override fun setPrimaryStartingToHide(startingToHide: Boolean) {
_primaryBouncerStartingToHide.value = startingToHide
}
@@ -122,7 +110,7 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
_isBackButtonEnabled.value = isBackButtonEnabled
}
- override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
- _onScreenTurnedOff.value = onScreenTurnedOff
+ override fun setSideFpsShowing(isShowing: Boolean) {
+ _sideFpsShowing.value = isShowing
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 1a371c73550c..194ed02712b2 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -47,6 +47,9 @@ class FakeKeyguardRepository : KeyguardRepository {
private val _isKeyguardShowing = MutableStateFlow(false)
override val isKeyguardShowing: Flow<Boolean> = _isKeyguardShowing
+ private val _isKeyguardUnlocked = MutableStateFlow(false)
+ override val isKeyguardUnlocked: Flow<Boolean> = _isKeyguardUnlocked
+
private val _isKeyguardOccluded = MutableStateFlow(false)
override val isKeyguardOccluded: Flow<Boolean> = _isKeyguardOccluded
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
index eac1bd145033..16442bb525b6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
@@ -37,7 +37,7 @@ class FakeKeyguardTransitionRepository : KeyguardTransitionRepository {
_transitions.emit(step)
}
- override fun startTransition(info: TransitionInfo): UUID? {
+ override fun startTransition(info: TransitionInfo, resetIfCanceled: Boolean): UUID? {
return null
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
index 251014fc50b3..4242c1635468 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
@@ -22,6 +22,7 @@ import android.content.pm.UserInfo
import android.os.UserHandle
import android.test.mock.MockContentResolver
import com.android.systemui.util.mockito.mock
+import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
/** A fake [UserTracker] to be used in tests. */
@@ -66,11 +67,19 @@ class FakeUserTracker(
_userId = _userInfo.id
_userHandle = UserHandle.of(_userId)
+ onUserChanging()
+ onUserChanged()
+ }
+
+ fun onUserChanging(userId: Int = _userId) {
+ val copy = callbacks.toList()
+ val latch = CountDownLatch(copy.size)
+ copy.forEach { it.onUserChanging(userId, userContext, latch) }
+ }
+
+ fun onUserChanged(userId: Int = _userId) {
val copy = callbacks.toList()
- copy.forEach {
- it.onUserChanging(_userId, userContext)
- it.onUserChanged(_userId, userContext)
- }
+ copy.forEach { it.onUserChanged(userId, userContext) }
}
fun onProfileChanged() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt
new file mode 100644
index 000000000000..0c9ce0f145f1
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.util
+
+import android.content.DialogInterface
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.verify
+import org.mockito.stubbing.Stubber
+
+class FakeSystemUIDialogController {
+
+ val dialog: SystemUIDialog = mock()
+
+ private val clickListeners: MutableMap<Int, DialogInterface.OnClickListener> = mutableMapOf()
+
+ init {
+ saveListener(DialogInterface.BUTTON_POSITIVE)
+ .whenever(dialog)
+ .setPositiveButton(any(), any())
+ saveListener(DialogInterface.BUTTON_POSITIVE)
+ .whenever(dialog)
+ .setPositiveButton(any(), any(), any())
+
+ saveListener(DialogInterface.BUTTON_NEGATIVE)
+ .whenever(dialog)
+ .setNegativeButton(any(), any())
+ saveListener(DialogInterface.BUTTON_NEGATIVE)
+ .whenever(dialog)
+ .setNegativeButton(any(), any(), any())
+
+ saveListener(DialogInterface.BUTTON_NEUTRAL).whenever(dialog).setNeutralButton(any(), any())
+ saveListener(DialogInterface.BUTTON_NEUTRAL)
+ .whenever(dialog)
+ .setNeutralButton(any(), any(), any())
+ }
+
+ fun clickNegative() {
+ performClick(DialogInterface.BUTTON_NEGATIVE, "This dialog has no negative button")
+ }
+
+ fun clickPositive() {
+ performClick(DialogInterface.BUTTON_POSITIVE, "This dialog has no positive button")
+ }
+
+ fun clickNeutral() {
+ performClick(DialogInterface.BUTTON_NEUTRAL, "This dialog has no neutral button")
+ }
+
+ fun cancel() {
+ val captor = ArgumentCaptor.forClass(DialogInterface.OnCancelListener::class.java)
+ verify(dialog).setOnCancelListener(captor.capture())
+ captor.value.onCancel(dialog)
+ }
+
+ private fun performClick(which: Int, errorMessage: String) {
+ clickListeners
+ .getOrElse(which) { throw IllegalAccessException(errorMessage) }
+ .onClick(dialog, which)
+ }
+
+ private fun saveListener(which: Int): Stubber = doAnswer {
+ val listener = it.getArgument<DialogInterface.OnClickListener>(1)
+ clickListeners[which] = listener
+ Unit
+ }
+}
diff --git a/packages/SystemUI/unfold/Android.bp b/packages/SystemUI/unfold/Android.bp
index 180b611aa13b..2e0a9462ffbe 100644
--- a/packages/SystemUI/unfold/Android.bp
+++ b/packages/SystemUI/unfold/Android.bp
@@ -35,6 +35,7 @@ android_library {
],
kotlincflags: ["-Xjvm-default=enable"],
java_version: "1.8",
+ sdk_version: "current",
min_sdk_version: "current",
plugins: ["dagger2-compiler"],
}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
index 068347cfe9d8..c3a6cf035d09 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
@@ -19,14 +19,15 @@ package com.android.systemui.unfold
import android.content.ContentResolver
import android.content.Context
import android.hardware.SensorManager
+import android.hardware.display.DisplayManager
import android.os.Handler
-import android.view.IWindowManager
import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.dagger.UnfoldMain
import com.android.systemui.unfold.dagger.UnfoldSingleThreadBg
import com.android.systemui.unfold.progress.RemoteUnfoldTransitionReceiver
import com.android.systemui.unfold.updates.FoldProvider
import com.android.systemui.unfold.updates.RotationChangeProvider
+import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
import com.android.systemui.unfold.util.CurrentActivityTypeProvider
import com.android.systemui.unfold.util.UnfoldTransitionATracePrefix
@@ -61,12 +62,13 @@ interface UnfoldSharedComponent {
@BindsInstance @UnfoldMain executor: Executor,
@BindsInstance @UnfoldSingleThreadBg singleThreadBgExecutor: Executor,
@BindsInstance @UnfoldTransitionATracePrefix tracingTagPrefix: String,
- @BindsInstance windowManager: IWindowManager,
+ @BindsInstance displayManager: DisplayManager,
@BindsInstance contentResolver: ContentResolver = context.contentResolver
): UnfoldSharedComponent
}
val unfoldTransitionProvider: Optional<UnfoldTransitionProgressProvider>
+ val hingeAngleProvider: HingeAngleProvider
val rotationChangeProvider: RotationChangeProvider
}
@@ -84,8 +86,9 @@ interface RemoteUnfoldSharedComponent {
@BindsInstance context: Context,
@BindsInstance config: UnfoldTransitionConfig,
@BindsInstance @UnfoldMain executor: Executor,
+ @BindsInstance @UnfoldMain handler: Handler,
@BindsInstance @UnfoldSingleThreadBg singleThreadBgExecutor: Executor,
- @BindsInstance windowManager: IWindowManager,
+ @BindsInstance displayManager: DisplayManager,
@BindsInstance @UnfoldTransitionATracePrefix tracingTagPrefix: String,
): RemoteUnfoldSharedComponent
}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
index 8eb79df55496..18399194434a 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
@@ -19,8 +19,8 @@ package com.android.systemui.unfold
import android.content.Context
import android.hardware.SensorManager
+import android.hardware.display.DisplayManager
import android.os.Handler
-import android.view.IWindowManager
import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.updates.FoldProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
@@ -47,7 +47,7 @@ fun createUnfoldSharedComponent(
mainExecutor: Executor,
singleThreadBgExecutor: Executor,
tracingTagPrefix: String,
- windowManager: IWindowManager,
+ displayManager: DisplayManager,
): UnfoldSharedComponent =
DaggerUnfoldSharedComponent.factory()
.create(
@@ -61,7 +61,7 @@ fun createUnfoldSharedComponent(
mainExecutor,
singleThreadBgExecutor,
tracingTagPrefix,
- windowManager,
+ displayManager,
)
/**
@@ -73,16 +73,18 @@ fun createRemoteUnfoldSharedComponent(
context: Context,
config: UnfoldTransitionConfig,
mainExecutor: Executor,
+ mainHandler: Handler,
singleThreadBgExecutor: Executor,
tracingTagPrefix: String,
- windowManager: IWindowManager,
+ displayManager: DisplayManager,
): RemoteUnfoldSharedComponent =
DaggerRemoteUnfoldSharedComponent.factory()
.create(
context,
config,
mainExecutor,
+ mainHandler,
singleThreadBgExecutor,
- windowManager,
+ displayManager,
tracingTagPrefix,
)
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
index 4622464b204d..c437e5c23d1b 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
@@ -21,7 +21,6 @@ import android.util.FloatProperty
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
import javax.inject.Inject
@@ -59,12 +58,15 @@ constructor(private val foldStateProvider: FoldStateProvider) :
}
override fun onFoldUpdate(@FoldUpdate update: Int) {
- when (update) {
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> animator.start()
- FOLD_UPDATE_FINISH_CLOSED -> animator.cancel()
+ if (update == FOLD_UPDATE_FINISH_CLOSED) {
+ animator.cancel()
}
}
+ override fun onUnfoldedScreenAvailable() {
+ animator.start()
+ }
+
override fun addCallback(listener: TransitionProgressListener) {
listeners.add(listener)
}
@@ -73,8 +75,6 @@ constructor(private val foldStateProvider: FoldStateProvider) :
listeners.remove(listener)
}
- override fun onHingeAngleUpdate(angle: Float) {}
-
private object AnimationProgressProperty :
FloatProperty<FixedTimingTransitionProgressProvider>("animation_progress") {
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
index 6ffbe5aa25c0..28e493651137 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
@@ -16,7 +16,6 @@
package com.android.systemui.unfold.progress
import android.os.Trace
-import android.os.Trace.TRACE_TAG_APP
import android.util.Log
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.FloatPropertyCompat
@@ -28,7 +27,6 @@ import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
@@ -78,21 +76,11 @@ class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
override fun onFoldUpdate(@FoldUpdate update: Int) {
when (update) {
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> {
- startTransition(startValue = 0f)
-
- // Stop the animation if the device has already opened by the time when
- // the display is available as we won't receive the full open event anymore
- if (foldStateProvider.isFinishedOpening) {
- cancelTransition(endValue = 1f, animate = true)
- }
- }
FOLD_UPDATE_FINISH_FULL_OPEN, FOLD_UPDATE_FINISH_HALF_OPEN -> {
// Do not cancel if we haven't started the transition yet.
// This could happen when we fully unfolded the device before the screen
// became available. In this case we start and immediately cancel the animation
- // in FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE event handler, so we don't need to
- // cancel it here.
+ // in onUnfoldedScreenAvailable event handler, so we don't need to cancel it here.
if (isTransitionRunning) {
cancelTransition(endValue = 1f, animate = true)
}
@@ -121,7 +109,17 @@ class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
if (DEBUG) {
Log.d(TAG, "onFoldUpdate = ${update.name()}")
- Trace.traceCounter(Trace.TRACE_TAG_APP, "fold_update", update)
+ Trace.setCounter("fold_update", update.toLong())
+ }
+ }
+
+ override fun onUnfoldedScreenAvailable() {
+ startTransition(startValue = 0f)
+
+ // Stop the animation if the device has already opened by the time when
+ // the display is available as we won't receive the full open event anymore
+ if (foldStateProvider.isFinishedOpening) {
+ cancelTransition(endValue = 1f, animate = true)
}
}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
index 97c9ba99f096..d653fc7beff2 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
@@ -54,6 +54,7 @@ constructor(
@FoldUpdate private var lastFoldUpdate: Int? = null
@FloatRange(from = 0.0, to = 180.0) private var lastHingeAngle: Float = 0f
+ @FloatRange(from = 0.0, to = 180.0) private var lastHingeAngleBeforeTransition: Float = 0f
private val hingeAngleListener = HingeAngleListener()
private val screenListener = ScreenStatusListener()
@@ -112,29 +113,45 @@ constructor(
private fun onHingeAngle(angle: Float) {
if (DEBUG) {
- Log.d(TAG, "Hinge angle: $angle, lastHingeAngle: $lastHingeAngle")
- Trace.traceCounter(Trace.TRACE_TAG_APP, "hinge_angle", angle.toInt())
+ Log.d(
+ TAG,
+ "Hinge angle: $angle, " +
+ "lastHingeAngle: $lastHingeAngle, " +
+ "lastHingeAngleBeforeTransition: $lastHingeAngleBeforeTransition"
+ )
+ Trace.setCounter( "hinge_angle", angle.toLong())
}
- val isClosing = angle < lastHingeAngle
+ val currentDirection =
+ if (angle < lastHingeAngle) FOLD_UPDATE_START_CLOSING else FOLD_UPDATE_START_OPENING
+ if (isTransitionInProgress && currentDirection != lastFoldUpdate) {
+ lastHingeAngleBeforeTransition = lastHingeAngle
+ }
+
+ val isClosing = angle < lastHingeAngleBeforeTransition
+ val transitionUpdate =
+ if (isClosing) FOLD_UPDATE_START_CLOSING else FOLD_UPDATE_START_OPENING
+ val angleChangeSurpassedThreshold =
+ Math.abs(angle - lastHingeAngleBeforeTransition) > HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES
val isFullyOpened = FULLY_OPEN_DEGREES - angle < FULLY_OPEN_THRESHOLD_DEGREES
- val closingEventDispatched = lastFoldUpdate == FOLD_UPDATE_START_CLOSING
+ val eventNotAlreadyDispatched = lastFoldUpdate != transitionUpdate
val screenAvailableEventSent = isUnfoldHandled
- if (isClosing // hinge angle should be decreasing since last update
- && !closingEventDispatched // we haven't sent closing event already
- && !isFullyOpened // do not send closing event if we are in fully opened hinge
+ if (
+ angleChangeSurpassedThreshold && // Do not react immediately to small changes in angle
+ eventNotAlreadyDispatched && // we haven't sent transition event already
+ !isFullyOpened && // do not send transition event if we are in fully opened hinge
// angle range as closing threshold could overlap this range
- && screenAvailableEventSent // do not send closing event if we are still in
- // the process of turning on the inner display
- && isClosingThresholdMet(angle) // hinge angle is below certain threshold.
+ screenAvailableEventSent && // do not send transition event if we are still in the
+ // process of turning on the inner display
+ isClosingThresholdMet(angle) // hinge angle is below certain threshold.
) {
- notifyFoldUpdate(FOLD_UPDATE_START_CLOSING)
+ notifyFoldUpdate(transitionUpdate, lastHingeAngle)
}
if (isTransitionInProgress) {
if (isFullyOpened) {
- notifyFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN)
+ notifyFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN, angle)
cancelTimeout()
} else {
// The timeout will trigger some constant time after the last angle update.
@@ -146,7 +163,7 @@ constructor(
outputListeners.forEach { it.onHingeAngleUpdate(angle) }
}
- private fun isClosingThresholdMet(currentAngle: Float) : Boolean {
+ private fun isClosingThresholdMet(currentAngle: Float): Boolean {
val closingThreshold = getClosingThreshold()
return closingThreshold == null || currentAngle < closingThreshold
}
@@ -179,23 +196,29 @@ constructor(
if (isFolded) {
hingeAngleProvider.stop()
- notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED)
+ notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED, lastHingeAngle)
cancelTimeout()
isUnfoldHandled = false
} else {
- notifyFoldUpdate(FOLD_UPDATE_START_OPENING)
+ notifyFoldUpdate(FOLD_UPDATE_START_OPENING, lastHingeAngle)
rescheduleAbortAnimationTimeout()
hingeAngleProvider.start()
}
}
}
- private fun notifyFoldUpdate(@FoldUpdate update: Int) {
+ private fun notifyFoldUpdate(@FoldUpdate update: Int, angle: Float) {
if (DEBUG) {
Log.d(TAG, update.name())
}
+ val previouslyTransitioning = isTransitionInProgress
+
outputListeners.forEach { it.onFoldUpdate(update) }
lastFoldUpdate = update
+
+ if (previouslyTransitioning != isTransitionInProgress) {
+ lastHingeAngleBeforeTransition = angle
+ }
}
private fun rescheduleAbortAnimationTimeout() {
@@ -209,7 +232,8 @@ constructor(
handler.removeCallbacks(timeoutRunnable)
}
- private fun cancelAnimation(): Unit = notifyFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN)
+ private fun cancelAnimation(): Unit =
+ notifyFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN, lastHingeAngle)
private inner class ScreenStatusListener : ScreenStatusProvider.ScreenListener {
@@ -221,7 +245,7 @@ constructor(
// receive 'folded' event. If SystemUI started when device is already folded it will
// still receive 'folded' event on startup.
if (!isFolded && !isUnfoldHandled) {
- outputListeners.forEach { it.onFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) }
+ outputListeners.forEach { it.onUnfoldedScreenAvailable() }
isUnfoldHandled = true
}
}
@@ -257,7 +281,6 @@ fun @receiver:FoldUpdate Int.name() =
when (this) {
FOLD_UPDATE_START_OPENING -> "START_OPENING"
FOLD_UPDATE_START_CLOSING -> "START_CLOSING"
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> "UNFOLDED_SCREEN_AVAILABLE"
FOLD_UPDATE_FINISH_HALF_OPEN -> "FINISH_HALF_OPEN"
FOLD_UPDATE_FINISH_FULL_OPEN -> "FINISH_FULL_OPEN"
FOLD_UPDATE_FINISH_CLOSED -> "FINISH_CLOSED"
@@ -270,5 +293,8 @@ private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
/** Threshold after which we consider the device fully unfolded. */
@VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f
+/** Threshold after which hinge angle updates are considered. This is to eliminate noise. */
+@VisibleForTesting const val HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES = 7.5f
+
/** Fold animation on top of apps only when the angle exceeds this threshold. */
@VisibleForTesting const val START_CLOSING_ON_APPS_THRESHOLD_DEGREES = 60
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
index c7a8bf336777..0af372f9da24 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
@@ -31,8 +31,9 @@ interface FoldStateProvider : CallbackController<FoldUpdatesListener> {
val isFinishedOpening: Boolean
interface FoldUpdatesListener {
- fun onHingeAngleUpdate(@FloatRange(from = 0.0, to = 180.0) angle: Float)
- fun onFoldUpdate(@FoldUpdate update: Int)
+ @JvmDefault fun onHingeAngleUpdate(@FloatRange(from = 0.0, to = 180.0) angle: Float) {}
+ @JvmDefault fun onFoldUpdate(@FoldUpdate update: Int) {}
+ @JvmDefault fun onUnfoldedScreenAvailable() {}
}
@IntDef(
@@ -40,7 +41,6 @@ interface FoldStateProvider : CallbackController<FoldUpdatesListener> {
[
FOLD_UPDATE_START_OPENING,
FOLD_UPDATE_START_CLOSING,
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE,
FOLD_UPDATE_FINISH_HALF_OPEN,
FOLD_UPDATE_FINISH_FULL_OPEN,
FOLD_UPDATE_FINISH_CLOSED])
@@ -50,7 +50,6 @@ interface FoldStateProvider : CallbackController<FoldUpdatesListener> {
const val FOLD_UPDATE_START_OPENING = 0
const val FOLD_UPDATE_START_CLOSING = 1
-const val FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE = 2
-const val FOLD_UPDATE_FINISH_HALF_OPEN = 3
-const val FOLD_UPDATE_FINISH_FULL_OPEN = 4
-const val FOLD_UPDATE_FINISH_CLOSED = 5
+const val FOLD_UPDATE_FINISH_HALF_OPEN = 2
+const val FOLD_UPDATE_FINISH_FULL_OPEN = 3
+const val FOLD_UPDATE_FINISH_CLOSED = 4
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/RotationChangeProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/RotationChangeProvider.kt
index 0cf8224d3a3f..ce8f1a178d05 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/RotationChangeProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/RotationChangeProvider.kt
@@ -17,36 +17,32 @@
package com.android.systemui.unfold.updates
import android.content.Context
+import android.hardware.display.DisplayManager
+import android.os.Handler
import android.os.RemoteException
-import android.view.IRotationWatcher
-import android.view.IWindowManager
-import android.view.Surface.Rotation
import com.android.systemui.unfold.dagger.UnfoldMain
import com.android.systemui.unfold.util.CallbackController
-import java.util.concurrent.Executor
import javax.inject.Inject
/**
- * Allows to subscribe to rotation changes.
- *
- * This is needed as rotation updates from [IWindowManager] are received in a binder thread, while
- * most of the times we want them in the main one. Updates are provided for the display associated
+ * Allows to subscribe to rotation changes. Updates are provided for the display associated
* to [context].
*/
class RotationChangeProvider
@Inject
constructor(
- private val windowManagerInterface: IWindowManager,
+ private val displayManager: DisplayManager,
private val context: Context,
- @UnfoldMain private val mainExecutor: Executor,
+ @UnfoldMain private val mainHandler: Handler,
) : CallbackController<RotationChangeProvider.RotationListener> {
private val listeners = mutableListOf<RotationListener>()
- private val rotationWatcher = RotationWatcher()
+ private val displayListener = RotationDisplayListener()
+ private var lastRotation: Int? = null
override fun addCallback(listener: RotationListener) {
- mainExecutor.execute {
+ mainHandler.post {
if (listeners.isEmpty()) {
subscribeToRotation()
}
@@ -55,17 +51,18 @@ constructor(
}
override fun removeCallback(listener: RotationListener) {
- mainExecutor.execute {
+ mainHandler.post {
listeners -= listener
if (listeners.isEmpty()) {
unsubscribeToRotation()
+ lastRotation = null
}
}
}
private fun subscribeToRotation() {
try {
- windowManagerInterface.watchRotation(rotationWatcher, context.displayId)
+ displayManager.registerDisplayListener(displayListener, mainHandler)
} catch (e: RemoteException) {
throw e.rethrowFromSystemServer()
}
@@ -73,7 +70,7 @@ constructor(
private fun unsubscribeToRotation() {
try {
- windowManagerInterface.removeRotationWatcher(rotationWatcher)
+ displayManager.unregisterDisplayListener(displayListener)
} catch (e: RemoteException) {
throw e.rethrowFromSystemServer()
}
@@ -82,12 +79,25 @@ constructor(
/** Gets notified of rotation changes. */
fun interface RotationListener {
/** Called once rotation changes. */
- fun onRotationChanged(@Rotation newRotation: Int)
+ fun onRotationChanged(newRotation: Int)
}
- private inner class RotationWatcher : IRotationWatcher.Stub() {
- override fun onRotationChanged(rotation: Int) {
- mainExecutor.execute { listeners.forEach { it.onRotationChanged(rotation) } }
+ private inner class RotationDisplayListener : DisplayManager.DisplayListener {
+
+ override fun onDisplayChanged(displayId: Int) {
+ val display = context.display ?: return
+
+ if (displayId == display.displayId) {
+ val currentRotation = display.rotation
+ if (lastRotation == null || lastRotation != currentRotation) {
+ listeners.forEach { it.onRotationChanged(currentRotation) }
+ lastRotation = currentRotation
+ }
+ }
}
+
+ override fun onDisplayAdded(displayId: Int) {}
+
+ override fun onDisplayRemoved(displayId: Int) {}
}
}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
index 06ca153b694b..ce5c5f91914b 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
@@ -79,10 +79,9 @@ constructor(
companion object {
fun ContentResolver.areAnimationsEnabled(): Boolean {
val animationScale =
- Settings.Global.getStringForUser(
+ Settings.Global.getString(
this,
Settings.Global.ANIMATOR_DURATION_SCALE,
- this.userId
)
?.toFloatOrNull()
?: 1f
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
index b7bab3e5ed5a..f9751d9c279c 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
@@ -47,6 +47,7 @@ constructor(source: UnfoldTransitionProgressProvider? = null) :
/**
* Sets the source for the unfold transition progress updates. Replaces current provider if it
* is already set
+ *
* @param provider transition provider that emits transition progress updates
*/
fun setSourceProvider(provider: UnfoldTransitionProgressProvider?) {
diff --git a/packages/VpnDialogs/res/values-fr/strings.xml b/packages/VpnDialogs/res/values-fr/strings.xml
index 27ebfb01f098..91a995a591ee 100644
--- a/packages/VpnDialogs/res/values-fr/strings.xml
+++ b/packages/VpnDialogs/res/values-fr/strings.xml
@@ -32,6 +32,6 @@
<string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Modifier les paramètres VPN"</string>
<string name="configure" msgid="4905518375574791375">"Configurer"</string>
<string name="disconnect" msgid="971412338304200056">"Déconnecter"</string>
- <string name="open_app" msgid="3717639178595958667">"Ouvrir l\'application"</string>
+ <string name="open_app" msgid="3717639178595958667">"Ouvrir l\'appli"</string>
<string name="dismiss" msgid="6192859333764711227">"Ignorer"</string>
</resources>
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 29194c58bd0c..3818a884c94a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1848,6 +1848,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
AccessibilityServiceInfo accessibilityServiceInfo;
try {
accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
+ if (!accessibilityServiceInfo.isWithinParcelableSize()) {
+ Slog.e(LOG_TAG, "Skipping service "
+ + accessibilityServiceInfo.getResolveInfo().getComponentInfo()
+ + " because service info size is larger than safe parcelable limits.");
+ continue;
+ }
if (userState.mCrashedServices.contains(serviceInfo.getComponentName())) {
// Restore the crashed attribute.
accessibilityServiceInfo.crashed = true;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d78fe8628c60..f0dac2607a4e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3831,8 +3831,20 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int callingAppId = UserHandle.getAppId(callingUid);
- userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ ProcessRecord proc;
+ synchronized (mPidsSelfLocked) {
+ proc = mPidsSelfLocked.get(callingPid);
+ }
+ final boolean hasKillAllPermission = PERMISSION_GRANTED == checkPermission(
+ android.Manifest.permission.FORCE_STOP_PACKAGES, callingPid, callingUid)
+ || UserHandle.isCore(callingUid)
+ || (proc != null && proc.info.isSystemApp());
+
+ userId = mUserController.handleIncomingUser(callingPid, callingUid,
userId, true, ALLOW_FULL_ONLY, "killBackgroundProcesses", null);
final int[] userIds = mUserController.expandUserId(userId);
@@ -3847,7 +3859,7 @@ public class ActivityManagerService extends IActivityManager.Stub
targetUserId));
} catch (RemoteException e) {
}
- if (appId == -1) {
+ if (appId == -1 || (!hasKillAllPermission && appId != callingAppId)) {
Slog.w(TAG, "Invalid packageName: " + packageName);
return;
}
@@ -3875,6 +3887,22 @@ public class ActivityManagerService extends IActivityManager.Stub
throw new SecurityException(msg);
}
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+
+ ProcessRecord proc;
+ synchronized (mPidsSelfLocked) {
+ proc = mPidsSelfLocked.get(callingPid);
+ }
+ if (callingUid >= FIRST_APPLICATION_UID
+ && (proc == null || !proc.info.isSystemApp())) {
+ final String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
+ + callingPid + ", uid=" + callingUid + " is not allowed";
+ Slog.w(TAG, msg);
+ // Silently return to avoid existing apps from crashing.
+ return;
+ }
+
final long callingId = Binder.clearCallingIdentity();
try {
synchronized (this) {
@@ -13089,12 +13117,17 @@ public class ActivityManagerService extends IActivityManager.Stub
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, String receiverId, IIntentReceiver receiver,
IntentFilter filter, String permission, int userId, int flags) {
+ enforceNotIsolatedCaller("registerReceiver");
+
// Allow Sandbox process to register only unexported receivers.
- if ((flags & Context.RECEIVER_NOT_EXPORTED) != 0) {
- enforceNotIsolatedCaller("registerReceiver");
- } else if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()) {
- enforceNotIsolatedOrSdkSandboxCaller("registerReceiver");
+ boolean unexported = (flags & Context.RECEIVER_NOT_EXPORTED) != 0;
+ if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()
+ && Process.isSdkSandboxUid(Binder.getCallingUid())
+ && !unexported) {
+ throw new SecurityException("SDK sandbox process not allowed to call "
+ + "registerReceiver");
}
+
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
final boolean visibleToInstantApps
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 9700e562b518..8c9373b98c58 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -3005,9 +3005,10 @@ public final class ProcessList {
hostingRecord.getDefiningUid(), hostingRecord.getDefiningProcessName());
final ProcessStateRecord state = r.mState;
- if (!mService.mBooted && !mService.mBooting
+ if (!isolated && !isSdkSandbox
&& userId == UserHandle.USER_SYSTEM
- && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
+ && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK
+ && (TextUtils.equals(proc, info.processName))) {
// The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
state.setSetSchedGroup(ProcessList.SCHED_GROUP_DEFAULT);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 0589cfc0967b..6410142278b5 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1218,6 +1218,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
sendILMsg(MSG_IL_BTA2DP_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs);
}
+ /*package*/ void setLeAudioTimeout(String address, int device, int delayMs) {
+ sendILMsg(MSG_IL_BTLEAUDIO_TIMEOUT, SENDMSG_QUEUE, device, address, delayMs);
+ }
+
/*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) {
synchronized (mDeviceStateLock) {
mBtHelper.setAvrcpAbsoluteVolumeSupported(supported);
@@ -1422,6 +1426,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1);
}
break;
+ case MSG_IL_BTLEAUDIO_TIMEOUT:
+ // msg.obj == address of LE Audio device
+ synchronized (mDeviceStateLock) {
+ mDeviceInventory.onMakeLeAudioDeviceUnavailableNow(
+ (String) msg.obj, msg.arg1);
+ }
+ break;
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
synchronized (mDeviceStateLock) {
@@ -1512,6 +1523,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
case MSG_I_BT_SERVICE_DISCONNECTED_PROFILE:
if (msg.arg1 != BluetoothProfile.HEADSET) {
synchronized (mDeviceStateLock) {
+ mBtHelper.onBtProfileDisconnected(msg.arg1);
mDeviceInventory.onBtProfileDisconnected(msg.arg1);
}
} else {
@@ -1648,11 +1660,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
// process set volume for Le Audio, obj is BleVolumeInfo
private static final int MSG_II_SET_LE_AUDIO_OUT_VOLUME = 46;
+ private static final int MSG_IL_BTLEAUDIO_TIMEOUT = 49;
+
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_L_SET_BT_ACTIVE_DEVICE:
case MSG_IL_BTA2DP_TIMEOUT:
+ case MSG_IL_BTLEAUDIO_TIMEOUT:
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
case MSG_TOGGLE_HDMI:
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
@@ -1743,6 +1758,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
case MSG_L_SET_BT_ACTIVE_DEVICE:
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_IL_BTA2DP_TIMEOUT:
+ case MSG_IL_BTLEAUDIO_TIMEOUT:
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
if (sLastDeviceConnectMsgTime >= time) {
// add a little delay to make sure messages are ordered as expected
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 35da73ef58c0..a74f4154eb85 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -374,7 +374,7 @@ public class AudioDeviceInventory {
case BluetoothProfile.LE_AUDIO:
case BluetoothProfile.LE_AUDIO_BROADCAST:
if (switchToUnavailable) {
- makeLeAudioDeviceUnavailable(address, btInfo.mAudioSystemDevice);
+ makeLeAudioDeviceUnavailableNow(address, btInfo.mAudioSystemDevice);
} else if (switchToAvailable) {
makeLeAudioDeviceAvailable(address, BtHelper.getName(btInfo.mDevice),
streamType, btInfo.mVolume == -1 ? -1 : btInfo.mVolume * 10,
@@ -486,6 +486,12 @@ public class AudioDeviceInventory {
}
}
+ /*package*/ void onMakeLeAudioDeviceUnavailableNow(String address, int device) {
+ synchronized (mDevicesLock) {
+ makeLeAudioDeviceUnavailableNow(address, device);
+ }
+ }
+
/*package*/ void onReportNewRoutes() {
int n = mRoutesObservers.beginBroadcast();
if (n > 0) {
@@ -883,10 +889,11 @@ public class AudioDeviceInventory {
new MediaMetrics.Item(mMetricsId + "disconnectLeAudio")
.record();
if (toRemove.size() > 0) {
- final int delay = checkSendBecomingNoisyIntentInt(device, 0,
+ final int delay = checkSendBecomingNoisyIntentInt(device,
+ AudioService.CONNECTION_STATE_DISCONNECTED,
AudioSystem.DEVICE_NONE);
toRemove.stream().forEach(deviceAddress ->
- makeLeAudioDeviceUnavailable(deviceAddress, device)
+ makeLeAudioDeviceUnavailableLater(deviceAddress, device, delay)
);
}
}
@@ -1187,9 +1194,21 @@ public class AudioDeviceInventory {
*/
mDeviceBroker.setBluetoothA2dpOnInt(true, false /*fromA2dp*/, eventSource);
- AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(device, address, name),
+ final int res = AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
+ device, address, name),
AudioSystem.DEVICE_STATE_AVAILABLE,
AudioSystem.AUDIO_FORMAT_DEFAULT);
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM failed to make available LE Audio device addr=" + address
+ + " error=" + res).printLog(TAG));
+ // TODO: connection failed, stop here
+ // TODO: return;
+ } else {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "LE Audio device addr=" + address + " now available").printLog(TAG));
+ }
+
mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
@@ -1210,11 +1229,23 @@ public class AudioDeviceInventory {
}
@GuardedBy("mDevicesLock")
- private void makeLeAudioDeviceUnavailable(String address, int device) {
+ private void makeLeAudioDeviceUnavailableNow(String address, int device) {
if (device != AudioSystem.DEVICE_NONE) {
- AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(device, address),
+ final int res = AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
+ device, address),
AudioSystem.DEVICE_STATE_UNAVAILABLE,
AudioSystem.AUDIO_FORMAT_DEFAULT);
+
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM failed to make unavailable LE Audio device addr=" + address
+ + " error=" + res).printLog(TAG));
+ // TODO: failed to disconnect, stop here
+ // TODO: return;
+ } else {
+ AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+ "LE Audio device addr=" + address + " made unavailable")).printLog(TAG));
+ }
mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
}
@@ -1222,6 +1253,14 @@ public class AudioDeviceInventory {
}
@GuardedBy("mDevicesLock")
+ private void makeLeAudioDeviceUnavailableLater(String address, int device, int delayMs) {
+ // the device will be made unavailable later, so consider it disconnected right away
+ mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
+ // send the delayed message to make the device unavailable later
+ mDeviceBroker.setLeAudioTimeout(address, device, delayMs);
+ }
+
+ @GuardedBy("mDevicesLock")
private void setCurrentAudioRouteNameIfPossible(String name, boolean fromA2dp) {
synchronized (mCurAudioRoutes) {
if (TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 9f1512825c3a..521f342455d6 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -8396,7 +8396,9 @@ public class AudioService extends IAudioService.Stub
if (isMutable()) {
// For call stream, align mute only when muted, not when index is set to 0
mVolumeGroupState.mute(
- forceMuteState ? mIsMuted : groupIndex == 0 || mIsMuted);
+ forceMuteState ? mIsMuted :
+ (groupIndex == 0 && !isCallStream(mStreamType))
+ || mIsMuted);
}
}
}
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 6cd42f87aede..691ce93b3f7b 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -279,7 +279,11 @@ public class BtHelper {
}
AudioService.sVolumeLogger.log(new AudioServiceEvents.VolumeEvent(
AudioServiceEvents.VolumeEvent.VOL_SET_AVRCP_VOL, index));
- mA2dp.setAvrcpAbsoluteVolume(index);
+ try {
+ mA2dp.setAvrcpAbsoluteVolume(index);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while changing abs volume", e);
+ }
}
/*package*/ synchronized @AudioSystem.AudioFormatNativeEnumForBtCodec int getA2dpCodec(
@@ -287,7 +291,12 @@ public class BtHelper {
if (mA2dp == null) {
return AudioSystem.AUDIO_FORMAT_DEFAULT;
}
- final BluetoothCodecStatus btCodecStatus = mA2dp.getCodecStatus(device);
+ BluetoothCodecStatus btCodecStatus = null;
+ try {
+ btCodecStatus = mA2dp.getCodecStatus(device);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while getting status of " + device, e);
+ }
if (btCodecStatus == null) {
return AudioSystem.AUDIO_FORMAT_DEFAULT;
}
@@ -421,7 +430,11 @@ public class BtHelper {
}
AudioService.sVolumeLogger.log(new AudioServiceEvents.VolumeEvent(
AudioServiceEvents.VolumeEvent.VOL_SET_LE_AUDIO_VOL, index, maxIndex));
- mLeAudio.setVolume(volume);
+ try {
+ mLeAudio.setVolume(volume);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while setting LE volume", e);
+ }
}
/*package*/ synchronized void setHearingAidVolume(int index, int streamType,
@@ -447,7 +460,11 @@ public class BtHelper {
AudioService.sVolumeLogger.log(new AudioServiceEvents.VolumeEvent(
AudioServiceEvents.VolumeEvent.VOL_SET_HEARING_AID_VOL, index, gainDB));
}
- mHearingAid.setVolume(gainDB);
+ try {
+ mHearingAid.setVolume(gainDB);
+ } catch (Exception e) {
+ Log.i(TAG, "Exception while setting hearing aid volume", e);
+ }
}
/*package*/ synchronized void onBroadcastScoConnectionState(int state) {
@@ -472,7 +489,7 @@ public class BtHelper {
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
- @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
+ //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void resetBluetoothSco() {
mScoAudioState = SCO_STATE_INACTIVE;
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
@@ -487,6 +504,35 @@ public class BtHelper {
mBluetoothHeadset = null;
}
+ //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
+ /*package*/ synchronized void onBtProfileDisconnected(int profile) {
+ switch (profile) {
+ case BluetoothProfile.A2DP:
+ mA2dp = null;
+ break;
+ case BluetoothProfile.HEARING_AID:
+ mHearingAid = null;
+ break;
+ case BluetoothProfile.LE_AUDIO:
+ mLeAudio = null;
+ break;
+
+ case BluetoothProfile.A2DP_SINK:
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ // shouldn't be received here as profile doesn't involve BtHelper
+ Log.e(TAG, "onBtProfileDisconnected: Not a profile handled by BtHelper "
+ + BluetoothProfile.getProfileName(profile));
+ break;
+
+ default:
+ // Not a valid profile to disconnect
+ Log.e(TAG, "onBtProfileDisconnected: Not a valid profile to disconnect "
+ + BluetoothProfile.getProfileName(profile));
+ break;
+ }
+ }
+
+ @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void onBtProfileConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
onHeadsetProfileConnected((BluetoothHeadset) proxy);
@@ -518,7 +564,7 @@ public class BtHelper {
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
- @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
+ //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void onHeadsetProfileConnected(BluetoothHeadset headset) {
// Discard timeout message
mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService();
@@ -672,7 +718,6 @@ public class BtHelper {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
switch(profile) {
case BluetoothProfile.A2DP:
- case BluetoothProfile.A2DP_SINK:
case BluetoothProfile.HEADSET:
case BluetoothProfile.HEARING_AID:
case BluetoothProfile.LE_AUDIO:
@@ -682,6 +727,10 @@ public class BtHelper {
mDeviceBroker.postBtProfileConnected(profile, proxy);
break;
+ case BluetoothProfile.A2DP_SINK:
+ // no A2DP sink functionality handled by BtHelper
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ // no broadcast functionality handled by BtHelper
default:
break;
}
@@ -690,14 +739,19 @@ public class BtHelper {
switch (profile) {
case BluetoothProfile.A2DP:
- case BluetoothProfile.A2DP_SINK:
case BluetoothProfile.HEADSET:
case BluetoothProfile.HEARING_AID:
case BluetoothProfile.LE_AUDIO:
- case BluetoothProfile.LE_AUDIO_BROADCAST:
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "BT profile service: disconnecting "
+ + BluetoothProfile.getProfileName(profile) + " profile"));
mDeviceBroker.postBtProfileDisconnected(profile);
break;
+ case BluetoothProfile.A2DP_SINK:
+ // no A2DP sink functionality handled by BtHelper
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ // no broadcast functionality handled by BtHelper
default:
break;
}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 8b579ac6539d..2292d9b60713 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -1127,6 +1127,14 @@ class AutomaticBrightnessController {
}
}
+ public float convertToFloatScale(float nits) {
+ if (mCurrentBrightnessMapper != null) {
+ return mCurrentBrightnessMapper.convertToFloatScale(nits);
+ } else {
+ return PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ }
+ }
+
public void recalculateSplines(boolean applyAdjustment, float[] adjustment) {
mCurrentBrightnessMapper.recalculateSplines(applyAdjustment, adjustment);
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 3fc50c4edf6d..d0471837d79b 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -322,6 +322,14 @@ public abstract class BrightnessMappingStrategy {
public abstract float convertToNits(float brightness);
/**
+ * Converts the provided nit value to a float scale value if possible.
+ *
+ * Returns {@link PowerManager.BRIGHTNESS_INVALID_FLOAT} if there's no available mapping for
+ * the nits to float scale.
+ */
+ public abstract float convertToFloatScale(float nits);
+
+ /**
* Adds a user interaction data point to the brightness mapping.
*
* This data point <b>must</b> exist on the brightness curve as a result of this call. This is
@@ -671,6 +679,11 @@ public abstract class BrightnessMappingStrategy {
}
@Override
+ public float convertToFloatScale(float nits) {
+ return PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ }
+
+ @Override
public void addUserDataPoint(float lux, float brightness) {
float unadjustedBrightness = getUnadjustedBrightness(lux);
if (mLoggingEnabled) {
@@ -913,6 +926,11 @@ public abstract class BrightnessMappingStrategy {
}
@Override
+ public float convertToFloatScale(float nits) {
+ return mNitsToBrightnessSpline.interpolate(nits);
+ }
+
+ @Override
public void addUserDataPoint(float lux, float brightness) {
float unadjustedBrightness = getUnadjustedBrightness(lux);
if (mLoggingEnabled) {
diff --git a/services/core/java/com/android/server/display/BrightnessSetting.java b/services/core/java/com/android/server/display/BrightnessSetting.java
index 74486113dcf9..9982d2eb31d1 100644
--- a/services/core/java/com/android/server/display/BrightnessSetting.java
+++ b/services/core/java/com/android/server/display/BrightnessSetting.java
@@ -117,6 +117,23 @@ public class BrightnessSetting {
}
}
+ /**
+ * @return The brightness for the default display in nits. Used when the underlying display
+ * device has changed but we want to persist the nit value.
+ */
+ float getBrightnessNitsForDefaultDisplay() {
+ return mPersistentDataStore.getBrightnessNitsForDefaultDisplay();
+ }
+
+ /**
+ * Set brightness in nits for the default display. Used when we want to persist the nit value
+ * even if the underlying display device changes.
+ * @param nits The brightness value in nits
+ */
+ void setBrightnessNitsForDefaultDisplay(float nits) {
+ mPersistentDataStore.setBrightnessNitsForDefaultDisplay(nits);
+ }
+
private void notifyListeners(float brightness) {
for (BrightnessSettingListener l : mListeners) {
l.onBrightnessChanged(brightness);
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 76d71e2b968a..bb39307bdc0d 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -22,6 +22,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.DisplayViewport;
import android.os.IBinder;
+import android.util.Slog;
import android.view.Display;
import android.view.DisplayAddress;
import android.view.Surface;
@@ -37,6 +38,7 @@ import java.io.PrintWriter;
* </p>
*/
abstract class DisplayDevice {
+ private static final String TAG = "DisplayDevice";
private static final Display.Mode EMPTY_DISPLAY_MODE = new Display.Mode.Builder().build();
private final DisplayAdapter mDisplayAdapter;
@@ -266,10 +268,13 @@ abstract class DisplayDevice {
/**
* Sets the display layer stack while in a transaction.
*/
- public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack) {
+ public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack,
+ int layerStackTag) {
if (mCurrentLayerStack != layerStack) {
mCurrentLayerStack = layerStack;
t.setDisplayLayerStack(mDisplayToken, layerStack);
+ Slog.i(TAG, "[" + layerStackTag + "] Layerstack set to " + layerStack + " for "
+ + mUniqueId);
}
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 4341634fb890..909c531c5e92 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -434,6 +434,8 @@ public final class DisplayManagerService extends SystemService {
private boolean mIsDocked;
private boolean mIsDreaming;
+ private boolean mBootCompleted = false;
+
private final BroadcastReceiver mIdleModeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -573,6 +575,12 @@ public final class DisplayManagerService extends SystemService {
}
}
} else if (phase == PHASE_BOOT_COMPLETED) {
+ synchronized (mSyncRoot) {
+ mBootCompleted = true;
+ for (int i = 0; i < mDisplayPowerControllers.size(); i++) {
+ mDisplayPowerControllers.valueAt(i).onBootCompleted();
+ }
+ }
mDisplayModeDirector.onBootCompleted();
mLogicalDisplayMapper.onBootCompleted();
}
@@ -2680,7 +2688,7 @@ public final class DisplayManagerService extends SystemService {
final DisplayPowerController displayPowerController = new DisplayPowerController(
mContext, mDisplayPowerCallbacks, mPowerHandler, mSensorManager,
mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
- () -> handleBrightnessChange(display), hbmMetadata);
+ () -> handleBrightnessChange(display), hbmMetadata, mBootCompleted);
mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController);
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 8025fa60ca2b..47e880a3fce2 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -133,6 +133,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private static final int MSG_BRIGHTNESS_RAMP_DONE = 12;
private static final int MSG_STATSD_HBM_BRIGHTNESS = 13;
private static final int MSG_SWITCH_USER = 14;
+ private static final int MSG_BOOT_COMPLETED = 15;
private static final int PROXIMITY_UNKNOWN = -1;
private static final int PROXIMITY_NEGATIVE = 0;
@@ -232,6 +233,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// True if should use light sensor to automatically determine doze screen brightness.
private final boolean mAllowAutoBrightnessWhileDozingConfig;
+ // True if we want to persist the brightness value in nits even if the underlying display
+ // device changes.
+ private final boolean mPersistBrightnessNitsForDefaultDisplay;
+
// True if the brightness config has changed and the short-term model needs to be reset
private boolean mShouldResetShortTermModel;
@@ -506,6 +511,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private boolean mIsEnabled;
private boolean mIsInTransition;
+ private boolean mBootCompleted;
+
/**
* Creates the display power controller.
*/
@@ -513,7 +520,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
- Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata) {
+ Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata,
+ boolean bootCompleted) {
mLogicalDisplay = logicalDisplay;
mDisplayId = mLogicalDisplay.getDisplayIdLocked();
final String displayIdStr = "[" + mDisplayId + "]";
@@ -579,6 +587,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
+ mPersistBrightnessNitsForDefaultDisplay = resources.getBoolean(
+ com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay);
+
mDisplayDeviceConfig = logicalDisplay.getPrimaryDisplayDeviceLocked()
.getDisplayDeviceConfig();
@@ -647,7 +658,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
loadProximitySensor();
- mCurrentScreenBrightnessSetting = getScreenBrightnessSetting();
+ loadNitBasedBrightnessSetting();
mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
@@ -655,6 +666,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ mBootCompleted = bootCompleted;
}
private void applyReduceBrightColorsSplineAdjustment() {
@@ -824,6 +836,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mDisplayStatsId = mUniqueDisplayId.hashCode();
mDisplayDeviceConfig = config;
loadFromDisplayDeviceConfig(token, info, hbmMetadata);
+ loadNitBasedBrightnessSetting();
/// Since the underlying display-device changed, we really don't know the
// last command that was sent to change it's state. Lets assume it is unknown so
@@ -868,10 +881,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mAutomaticBrightnessController.stop();
}
- if (mScreenOffBrightnessSensorController != null) {
- mScreenOffBrightnessSensorController.stop();
- }
-
if (mBrightnessSetting != null) {
mBrightnessSetting.unregisterListener(mBrightnessSettingListener);
}
@@ -1120,6 +1129,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.stop();
+ mScreenOffBrightnessSensorController = null;
}
loadScreenOffBrightnessSensor();
int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
@@ -1237,6 +1247,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mPowerState.stop();
mPowerState = null;
}
+
+ if (mScreenOffBrightnessSensorController != null) {
+ mScreenOffBrightnessSensorController.stop();
+ }
}
private void updatePowerState() {
@@ -1312,7 +1326,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.setLightSensorEnabled(mUseAutoBrightness
- && (state == Display.STATE_OFF || (state == Display.STATE_DOZE
+ && mIsEnabled && (state == Display.STATE_OFF || (state == Display.STATE_DOZE
&& !mAllowAutoBrightnessWhileDozingConfig)));
}
@@ -1358,8 +1372,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
sendOnProximityNegativeWithWakelock();
}
} else {
+ setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false;
mIgnoreProximityUntilChanged = false;
+
+ if (mScreenOffBecauseOfProximity) {
+ // The screen *was* off due to prox being near, but now there's no prox sensor, so
+ // let's turn the screen back on.
+ mScreenOffBecauseOfProximity = false;
+ skipRampBecauseOfProximityChangeToNegative = true;
+ sendOnProximityNegativeWithWakelock();
+ }
}
if (!mIsEnabled
@@ -1370,7 +1393,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Initialize things the first time the power state is changed.
if (mustInitialize) {
- initialize(state);
+ initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN);
}
// Animate the screen state change unless already animating.
@@ -2050,7 +2073,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
- if (!reportOnly && mPowerState.getScreenState() != state) {
+ if (!reportOnly && mPowerState.getScreenState() != state
+ && readyToUpdateDisplayState()) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
// TODO(b/153319140) remove when we can get this from the above trace invocation
SystemProperties.set("debug.tracing.screen_state", String.valueOf(state));
@@ -2491,10 +2515,37 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
return clampScreenBrightnessForVr(brightnessFloat);
}
+ private void loadNitBasedBrightnessSetting() {
+ if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
+ float brightnessNitsForDefaultDisplay =
+ mBrightnessSetting.getBrightnessNitsForDefaultDisplay();
+ if (brightnessNitsForDefaultDisplay >= 0) {
+ float brightnessForDefaultDisplay = convertToFloatScale(
+ brightnessNitsForDefaultDisplay);
+ if (isValidBrightnessValue(brightnessForDefaultDisplay)) {
+ mBrightnessSetting.setBrightness(brightnessForDefaultDisplay);
+ mCurrentScreenBrightnessSetting = brightnessForDefaultDisplay;
+ return;
+ }
+ }
+ }
+ mCurrentScreenBrightnessSetting = getScreenBrightnessSetting();
+ }
+
void setBrightness(float brightnessValue) {
// Update the setting, which will eventually call back into DPC to have us actually update
// the display with the new value.
mBrightnessSetting.setBrightness(brightnessValue);
+ if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
+ float nits = convertToNits(brightnessValue);
+ if (nits >= 0) {
+ mBrightnessSetting.setBrightnessNitsForDefaultDisplay(nits);
+ }
+ }
+ }
+
+ void onBootCompleted() {
+ mHandler.obtainMessage(MSG_BOOT_COMPLETED).sendToTarget();
}
private void updateScreenBrightnessSetting(float brightnessValue) {
@@ -2503,7 +2554,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
return;
}
setCurrentScreenBrightness(brightnessValue);
- mBrightnessSetting.setBrightness(brightnessValue);
+ setBrightness(brightnessValue);
}
private void setCurrentScreenBrightness(float brightnessValue) {
@@ -2582,6 +2633,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
return mAutomaticBrightnessController.convertToNits(brightness);
}
+ private float convertToFloatScale(float nits) {
+ if (mAutomaticBrightnessController == null) {
+ return PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ }
+ return mAutomaticBrightnessController.convertToFloatScale(nits);
+ }
+
@GuardedBy("mLock")
private void updatePendingProximityRequestsLocked() {
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
@@ -2642,6 +2700,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
};
+ /**
+ * Indicates whether the display state is ready to update. If this is the default display, we
+ * want to update it right away so that we can draw the boot animation on it. If it is not
+ * the default display, drawing the boot animation on it would look incorrect, so we need
+ * to wait until boot is completed.
+ * @return True if the display state is ready to update
+ */
+ private boolean readyToUpdateDisplayState() {
+ return mDisplayId == Display.DEFAULT_DISPLAY || mBootCompleted;
+ }
+
public void dump(final PrintWriter pw) {
synchronized (mLock) {
pw.println();
@@ -2668,25 +2737,27 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pw.println(" mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum);
pw.println(" mScreenBrightnessForVrDefault=" + mScreenBrightnessForVrDefault);
pw.println(" mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
- pw.println(" mAllowAutoBrightnessWhileDozingConfig=" +
- mAllowAutoBrightnessWhileDozingConfig);
+ pw.println(" mAllowAutoBrightnessWhileDozingConfig="
+ + mAllowAutoBrightnessWhileDozingConfig);
+ pw.println(" mPersistBrightnessNitsForDefaultDisplay="
+ + mPersistBrightnessNitsForDefaultDisplay);
pw.println(" mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp);
pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig);
pw.println(" mColorFadeEnabled=" + mColorFadeEnabled);
synchronized (mCachedBrightnessInfo) {
- pw.println(" mCachedBrightnessInfo.brightness=" +
- mCachedBrightnessInfo.brightness.value);
- pw.println(" mCachedBrightnessInfo.adjustedBrightness=" +
- mCachedBrightnessInfo.adjustedBrightness.value);
- pw.println(" mCachedBrightnessInfo.brightnessMin=" +
- mCachedBrightnessInfo.brightnessMin.value);
- pw.println(" mCachedBrightnessInfo.brightnessMax=" +
- mCachedBrightnessInfo.brightnessMax.value);
+ pw.println(" mCachedBrightnessInfo.brightness="
+ + mCachedBrightnessInfo.brightness.value);
+ pw.println(" mCachedBrightnessInfo.adjustedBrightness="
+ + mCachedBrightnessInfo.adjustedBrightness.value);
+ pw.println(" mCachedBrightnessInfo.brightnessMin="
+ + mCachedBrightnessInfo.brightnessMin.value);
+ pw.println(" mCachedBrightnessInfo.brightnessMax="
+ + mCachedBrightnessInfo.brightnessMax.value);
pw.println(" mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode.value);
- pw.println(" mCachedBrightnessInfo.hbmTransitionPoint=" +
- mCachedBrightnessInfo.hbmTransitionPoint.value);
- pw.println(" mCachedBrightnessInfo.brightnessMaxReason =" +
- mCachedBrightnessInfo.brightnessMaxReason.value);
+ pw.println(" mCachedBrightnessInfo.hbmTransitionPoint="
+ + mCachedBrightnessInfo.hbmTransitionPoint.value);
+ pw.println(" mCachedBrightnessInfo.brightnessMaxReason ="
+ + mCachedBrightnessInfo.brightnessMaxReason.value);
}
pw.println(" mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig);
pw.println(" mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig);
@@ -3177,6 +3248,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
case MSG_SWITCH_USER:
handleOnSwitchUser(msg.arg1);
break;
+
+ case MSG_BOOT_COMPLETED:
+ mBootCompleted = true;
+ updatePowerState();
+ break;
}
}
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index e6f27c1b0dd9..7dc412ed1cf8 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -494,7 +494,7 @@ final class LogicalDisplay {
DisplayDevice device,
boolean isBlanked) {
// Set the layer stack.
- device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack);
+ device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack, mDisplayId);
// Also inform whether the device is the same one sent to inputflinger for its layerstack.
// Prevent displays that are disabled from receiving input.
// TODO(b/188914255): Remove once input can dispatch against device vs layerstack.
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index 73131a1dc220..a8e0d58cc4ff 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -94,6 +94,7 @@ import java.util.Objects;
* &lt;/brightness-curve>
* &lt;/brightness-configuration>
* &lt;/brightness-configurations>
+ * &lt;brightness-nits-for-default-display>600&lt;/brightness-nits-for-default-display>
* &lt;/display-manager-state>
* </code>
*
@@ -130,6 +131,9 @@ final class PersistentDataStore {
private static final String TAG_RESOLUTION_HEIGHT = "resolution-height";
private static final String TAG_REFRESH_RATE = "refresh-rate";
+ private static final String TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY =
+ "brightness-nits-for-default-display";
+
// Remembered Wifi display devices.
private ArrayList<WifiDisplay> mRememberedWifiDisplays = new ArrayList<WifiDisplay>();
@@ -137,6 +141,8 @@ final class PersistentDataStore {
private final HashMap<String, DisplayState> mDisplayStates =
new HashMap<String, DisplayState>();
+ private float mBrightnessNitsForDefaultDisplay = -1;
+
// Display values which should be stable across the device's lifetime.
private final StableDeviceValues mStableDeviceValues = new StableDeviceValues();
@@ -312,6 +318,19 @@ final class PersistentDataStore {
return false;
}
+ public float getBrightnessNitsForDefaultDisplay() {
+ return mBrightnessNitsForDefaultDisplay;
+ }
+
+ public boolean setBrightnessNitsForDefaultDisplay(float nits) {
+ if (nits != mBrightnessNitsForDefaultDisplay) {
+ mBrightnessNitsForDefaultDisplay = nits;
+ setDirty();
+ return true;
+ }
+ return false;
+ }
+
public boolean setUserPreferredRefreshRate(DisplayDevice displayDevice, float refreshRate) {
final String displayDeviceUniqueId = displayDevice.getUniqueId();
if (!displayDevice.hasStableUniqueId() || displayDeviceUniqueId == null) {
@@ -513,6 +532,10 @@ final class PersistentDataStore {
if (parser.getName().equals(TAG_BRIGHTNESS_CONFIGURATIONS)) {
mGlobalBrightnessConfigurations.loadFromXml(parser);
}
+ if (parser.getName().equals(TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY)) {
+ String value = parser.nextText();
+ mBrightnessNitsForDefaultDisplay = Float.parseFloat(value);
+ }
}
}
@@ -592,6 +615,9 @@ final class PersistentDataStore {
serializer.startTag(null, TAG_BRIGHTNESS_CONFIGURATIONS);
mGlobalBrightnessConfigurations.saveToXml(serializer);
serializer.endTag(null, TAG_BRIGHTNESS_CONFIGURATIONS);
+ serializer.startTag(null, TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY);
+ serializer.text(Float.toString(mBrightnessNitsForDefaultDisplay));
+ serializer.endTag(null, TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY);
serializer.endTag(null, TAG_DISPLAY_MANAGER_STATE);
serializer.endDocument();
}
@@ -615,6 +641,7 @@ final class PersistentDataStore {
mStableDeviceValues.dump(pw, " ");
pw.println(" GlobalBrightnessConfigurations:");
mGlobalBrightnessConfigurations.dump(pw, " ");
+ pw.println(" mBrightnessNitsForDefaultDisplay=" + mBrightnessNitsForDefaultDisplay);
}
private static final class DisplayState {
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 97ab58764e1e..ccab7bc9f31d 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -123,15 +123,14 @@ final class DreamController {
final DreamRecord oldDream = mCurrentDream;
mCurrentDream = new DreamRecord(token, name, isPreviewMode, canDoze, userId, wakeLock);
if (oldDream != null) {
- if (!oldDream.mWakingGently) {
- // We will stop these previous dreams once the new dream is started.
- mPreviousDreams.add(oldDream);
- } else if (Objects.equals(oldDream.mName, mCurrentDream.mName)) {
+ if (Objects.equals(oldDream.mName, mCurrentDream.mName)) {
// We are attempting to start a dream that is currently waking up gently.
// Let's silently stop the old instance here to clear the dream state.
// This should happen after the new mCurrentDream is set to avoid announcing
// a "dream stopped" state.
stopDreamInstance(/* immediately */ true, "restarting same dream", oldDream);
+ } else {
+ mPreviousDreams.add(oldDream);
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 350aa6b2f686..2a807b2a3ef3 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -608,6 +608,9 @@ class MediaRouter2ServiceImpl {
/* package */ void updateRunningUserAndProfiles(int newActiveUserId) {
synchronized (mLock) {
if (mCurrentActiveUserId != newActiveUserId) {
+ Slog.i(TAG, TextUtils.formatSimple(
+ "switchUser | user: %d", newActiveUserId));
+
mCurrentActiveUserId = newActiveUserId;
for (int i = 0; i < mUserRecords.size(); i++) {
int userId = mUserRecords.keyAt(i);
@@ -679,6 +682,10 @@ class MediaRouter2ServiceImpl {
userRecord.mHandler.sendMessage(
obtainMessage(UserHandler::notifyRouterRegistered,
userRecord.mHandler, routerRecord));
+
+ Slog.i(TAG, TextUtils.formatSimple(
+ "registerRouter2 | package: %s, uid: %d, pid: %d, router: %d",
+ packageName, uid, pid, routerRecord.mRouterId));
}
@GuardedBy("mLock")
@@ -689,6 +696,11 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "unregisterRouter2 | package: %s, router: %d",
+ routerRecord.mPackageName,
+ routerRecord.mRouterId));
+
UserRecord userRecord = routerRecord.mUserRecord;
userRecord.mRouterRecords.remove(routerRecord);
routerRecord.mUserRecord.mHandler.sendMessage(
@@ -707,6 +719,11 @@ class MediaRouter2ServiceImpl {
if (routerRecord.mDiscoveryPreference.equals(discoveryRequest)) {
return;
}
+
+ Slog.i(TAG, TextUtils.formatSimple(
+ "setDiscoveryRequestWithRouter2 | router: %d, discovery request: %s",
+ routerRecord.mRouterId, discoveryRequest.toString()));
+
routerRecord.mDiscoveryPreference = discoveryRequest;
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::notifyDiscoveryPreferenceChangedToManagers,
@@ -724,6 +741,10 @@ class MediaRouter2ServiceImpl {
RouterRecord routerRecord = mAllRouterRecords.get(binder);
if (routerRecord != null) {
+ Slog.i(TAG, TextUtils.formatSimple(
+ "setRouteVolumeWithRouter2 | router: %d, volume: %d",
+ routerRecord.mRouterId, volume));
+
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::setRouteVolumeOnHandler,
routerRecord.mUserRecord.mHandler,
@@ -804,6 +825,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "selectRouteWithRouter2 | router: %d, route: %s",
+ routerRecord.mRouterId, route.getId()));
+
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::selectRouteOnHandler,
routerRecord.mUserRecord.mHandler,
@@ -819,6 +844,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "deselectRouteWithRouter2 | router: %d, route: %s",
+ routerRecord.mRouterId, route.getId()));
+
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::deselectRouteOnHandler,
routerRecord.mUserRecord.mHandler,
@@ -834,6 +863,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "transferToRouteWithRouter2 | router: %d, route: %s",
+ routerRecord.mRouterId, route.getId()));
+
String defaultRouteId =
routerRecord.mUserRecord.mHandler.mSystemProvider.getDefaultRoute().getId();
if (route.isSystemRoute() && !routerRecord.mHasModifyAudioRoutingPermission
@@ -859,6 +892,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "setSessionVolumeWithRouter2 | router: %d, session: %s, volume: %d",
+ routerRecord.mRouterId, uniqueSessionId, volume));
+
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::setSessionVolumeOnHandler,
routerRecord.mUserRecord.mHandler,
@@ -874,6 +911,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "releaseSessionWithRouter2 | router: %d, session: %s",
+ routerRecord.mRouterId, uniqueSessionId));
+
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::releaseSessionOnHandler,
routerRecord.mUserRecord.mHandler,
@@ -916,6 +957,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "registerManager | uid: %d, pid: %d, package: %s, user: %d",
+ uid, pid, packageName, userId));
+
mContext.enforcePermission(Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid,
"Must hold MEDIA_CONTENT_CONTROL permission.");
@@ -951,6 +996,13 @@ class MediaRouter2ServiceImpl {
return;
}
UserRecord userRecord = managerRecord.mUserRecord;
+
+ Slog.i(TAG, TextUtils.formatSimple(
+ "unregisterManager | package: %s, user: %d, manager: %d",
+ managerRecord.mPackageName,
+ userRecord.mUserId,
+ managerRecord.mManagerId));
+
userRecord.mManagerRecords.remove(managerRecord);
managerRecord.dispose();
disposeUserIfNeededLocked(userRecord); // since manager removed from user
@@ -962,6 +1014,10 @@ class MediaRouter2ServiceImpl {
if (managerRecord == null) {
return;
}
+
+ Slog.i(TAG, TextUtils.formatSimple(
+ "startScan | manager: %d", managerRecord.mManagerId));
+
managerRecord.startScan();
}
@@ -971,6 +1027,10 @@ class MediaRouter2ServiceImpl {
if (managerRecord == null) {
return;
}
+
+ Slog.i(TAG, TextUtils.formatSimple(
+ "stopScan | manager: %d", managerRecord.mManagerId));
+
managerRecord.stopScan();
}
@@ -984,6 +1044,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "setRouteVolumeWithManager | manager: %d, route: %s, volume: %d",
+ managerRecord.mManagerId, route.getId(), volume));
+
long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
managerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::setRouteVolumeOnHandler,
@@ -999,6 +1063,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "requestCreateSessionWithManager | manager: %d, route: %s",
+ managerRecord.mManagerId, route.getId()));
+
String packageName = oldSession.getClientPackageName();
RouterRecord routerRecord = managerRecord.mUserRecord.findRouterRecordLocked(packageName);
@@ -1044,6 +1112,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "selectRouteWithManager | manager: %d, session: %s, route: %s",
+ managerRecord.mManagerId, uniqueSessionId, route.getId()));
+
// Can be null if the session is system's or RCN.
RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
.findRouterWithSessionLocked(uniqueSessionId);
@@ -1065,6 +1137,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "deselectRouteWithManager | manager: %d, session: %s, route: %s",
+ managerRecord.mManagerId, uniqueSessionId, route.getId()));
+
// Can be null if the session is system's or RCN.
RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
.findRouterWithSessionLocked(uniqueSessionId);
@@ -1086,6 +1162,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "transferToRouteWithManager | manager: %d, session: %s, route: %s",
+ managerRecord.mManagerId, uniqueSessionId, route.getId()));
+
// Can be null if the session is system's or RCN.
RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
.findRouterWithSessionLocked(uniqueSessionId);
@@ -1107,6 +1187,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "setSessionVolumeWithManager | manager: %d, session: %s, volume: %d",
+ managerRecord.mManagerId, uniqueSessionId, volume));
+
long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
managerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::setSessionVolumeOnHandler,
@@ -1124,6 +1208,10 @@ class MediaRouter2ServiceImpl {
return;
}
+ Slog.i(TAG, TextUtils.formatSimple(
+ "releaseSessionWithManager | manager: %d, session: %s",
+ managerRecord.mManagerId, uniqueSessionId));
+
RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
.findRouterWithSessionLocked(uniqueSessionId);
@@ -1484,6 +1572,24 @@ class MediaRouter2ServiceImpl {
List<IMediaRouter2> routersWithModifyAudioRoutingPermission = getRouters(true);
List<IMediaRouter2> routersWithoutModifyAudioRoutingPermission = getRouters(false);
+
+ if (!addedRoutes.isEmpty()) {
+ // If routes were added, currentInfo cannot be null.
+ Slog.i(TAG,
+ toLoggingMessage(
+ /* source= */ "addProviderRoutes",
+ currentInfo.getUniqueId(),
+ (ArrayList) addedRoutes));
+ }
+ if (!removedRoutes.isEmpty()) {
+ // If routes were removed, prevInfo cannot be null.
+ Slog.i(TAG,
+ toLoggingMessage(
+ /* source= */ "removeProviderRoutes",
+ prevInfo.getUniqueId(),
+ (ArrayList) removedRoutes));
+ }
+
List<IMediaRouter2Manager> managers = getManagers();
List<MediaRoute2Info> defaultRoute = new ArrayList<>();
defaultRoute.add(mSystemProvider.getDefaultRoute());
@@ -1522,6 +1628,16 @@ class MediaRouter2ServiceImpl {
}
}
+ private static String toLoggingMessage(
+ String source, String providerId, ArrayList<MediaRoute2Info> routes) {
+ String routesString =
+ routes.stream()
+ .map(it -> String.format("%s | %s", it.getOriginalId(), it.getName()))
+ .collect(Collectors.joining(/* delimiter= */ ", "));
+ return TextUtils.formatSimple("%s | provider: %s, routes: [%s]",
+ source, providerId, routesString);
+ }
+
private int getLastProviderInfoIndex(@NonNull String providerId) {
for (int i = 0; i < mLastProviderInfos.size(); i++) {
MediaRoute2ProviderInfo providerInfo = mLastProviderInfos.get(i);
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index b75ba75e028b..c5a337d853a6 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -21,7 +21,9 @@ import static com.android.server.media.MediaSessionPolicyProvider.SESSION_POLICY
import android.media.Session2Token;
import android.media.session.MediaSession;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.Log;
+import android.util.Slog;
import android.util.SparseArray;
import java.io.PrintWriter;
@@ -82,6 +84,10 @@ class MediaSessionStack {
* @param record The record to add.
*/
public void addSession(MediaSessionRecordImpl record) {
+ Slog.i(TAG, TextUtils.formatSimple(
+ "addSession to bottom of stack | record: %s",
+ record
+ ));
mSessions.add(record);
clearCache(record.getUserId());
@@ -97,6 +103,10 @@ class MediaSessionStack {
* @param record The record to remove.
*/
public void removeSession(MediaSessionRecordImpl record) {
+ Slog.i(TAG, TextUtils.formatSimple(
+ "removeSession | record: %s",
+ record
+ ));
mSessions.remove(record);
if (mMediaButtonSession == record) {
// When the media button session is removed, nullify the media button session and do not
@@ -142,6 +152,10 @@ class MediaSessionStack {
public void onPlaybackStateChanged(
MediaSessionRecordImpl record, boolean shouldUpdatePriority) {
if (shouldUpdatePriority) {
+ Slog.i(TAG, TextUtils.formatSimple(
+ "onPlaybackStateChanged - Pushing session to top | record: %s",
+ record
+ ));
mSessions.remove(record);
mSessions.add(0, record);
clearCache(record.getUserId());
diff --git a/services/core/java/com/android/server/media/projection/OWNERS b/services/core/java/com/android/server/media/projection/OWNERS
index 9ca391013aa3..832bcd9d70e6 100644
--- a/services/core/java/com/android/server/media/projection/OWNERS
+++ b/services/core/java/com/android/server/media/projection/OWNERS
@@ -1,2 +1 @@
-michaelwr@google.com
-santoscordon@google.com
+include /media/java/android/media/projection/OWNERS
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ff10cbc19d5f..d11413937f8d 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.notification;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.NOT_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY;
@@ -6323,21 +6324,40 @@ public class NotificationManagerService extends SystemService {
checkCallerIsSystem();
mHandler.post(() -> {
synchronized (mNotificationLock) {
- // strip flag from all enqueued notifications. listeners will be informed
- // in post runnable.
- List<NotificationRecord> enqueued = findNotificationsByListLocked(
- mEnqueuedNotifications, pkg, null, notificationId, userId);
- for (int i = 0; i < enqueued.size(); i++) {
- removeForegroundServiceFlagLocked(enqueued.get(i));
- }
+ int count = getNotificationCount(pkg, userId);
+ boolean removeFgsNotification = false;
+ if (count > MAX_PACKAGE_NOTIFICATIONS) {
+ mUsageStats.registerOverCountQuota(pkg);
+ removeFgsNotification = true;
+ }
+ if (removeFgsNotification) {
+ NotificationRecord r = findNotificationLocked(pkg, null, notificationId,
+ userId);
+ if (r != null) {
+ if (DBG) {
+ Slog.d(TAG, "Remove FGS flag not allow. Cancel FGS notification");
+ }
+ removeFromNotificationListsLocked(r);
+ cancelNotificationLocked(r, false, REASON_APP_CANCEL, true,
+ null, SystemClock.elapsedRealtime());
+ }
+ } else {
+ // strip flag from all enqueued notifications. listeners will be informed
+ // in post runnable.
+ List<NotificationRecord> enqueued = findNotificationsByListLocked(
+ mEnqueuedNotifications, pkg, null, notificationId, userId);
+ for (int i = 0; i < enqueued.size(); i++) {
+ removeForegroundServiceFlagLocked(enqueued.get(i));
+ }
- // if posted notification exists, strip its flag and tell listeners
- NotificationRecord r = findNotificationByListLocked(
- mNotificationList, pkg, null, notificationId, userId);
- if (r != null) {
- removeForegroundServiceFlagLocked(r);
- mRankingHelper.sort(mNotificationList);
- mListeners.notifyPostedLocked(r, r);
+ // if posted notification exists, strip its flag and tell listeners
+ NotificationRecord r = findNotificationByListLocked(
+ mNotificationList, pkg, null, notificationId, userId);
+ if (r != null) {
+ removeForegroundServiceFlagLocked(r);
+ mRankingHelper.sort(mNotificationList);
+ mListeners.notifyPostedLocked(r, r);
+ }
}
}
});
@@ -6483,9 +6503,17 @@ public class NotificationManagerService extends SystemService {
checkRestrictedCategories(notification);
+ // Notifications passed to setForegroundService() have FLAG_FOREGROUND_SERVICE,
+ // but it's also possible that the app has called notify() with an update to an
+ // FGS notification that hasn't yet been displayed. Make sure we check for any
+ // FGS-related situation up front, outside of any locks so it's safe to call into
+ // the Activity Manager.
+ final ServiceNotificationPolicy policy = mAmi.applyForegroundServiceNotification(
+ notification, tag, id, pkg, userId);
+
// Fix the notification as best we can.
try {
- fixNotification(notification, pkg, tag, id, userId);
+ fixNotification(notification, pkg, tag, id, userId, notificationUid, policy);
} catch (Exception e) {
if (notification.isForegroundService()) {
throw new SecurityException("Invalid FGS notification", e);
@@ -6494,13 +6522,7 @@ public class NotificationManagerService extends SystemService {
return;
}
- // Notifications passed to setForegroundService() have FLAG_FOREGROUND_SERVICE,
- // but it's also possible that the app has called notify() with an update to an
- // FGS notification that hasn't yet been displayed. Make sure we check for any
- // FGS-related situation up front, outside of any locks so it's safe to call into
- // the Activity Manager.
- final ServiceNotificationPolicy policy = mAmi.applyForegroundServiceNotification(
- notification, tag, id, pkg, userId);
+
if (policy == ServiceNotificationPolicy.UPDATE_ONLY) {
// Proceed if the notification is already showing/known, otherwise ignore
// because the service lifecycle logic has retained responsibility for its
@@ -6663,14 +6685,20 @@ public class NotificationManagerService extends SystemService {
@VisibleForTesting
protected void fixNotification(Notification notification, String pkg, String tag, int id,
- int userId) throws NameNotFoundException, RemoteException {
+ @UserIdInt int userId, int notificationUid, ServiceNotificationPolicy fgsPolicy)
+ throws NameNotFoundException, RemoteException {
final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser(
pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
(userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId);
Notification.addFieldsFromContext(ai, notification);
- int canColorize = mPackageManagerClient.checkPermission(
- android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, pkg);
+ if (notification.isForegroundService() && fgsPolicy == NOT_FOREGROUND_SERVICE) {
+ notification.flags &= ~FLAG_FOREGROUND_SERVICE;
+ }
+
+ int canColorize = getContext().checkPermission(
+ android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, -1, notificationUid);
+
if (canColorize == PERMISSION_GRANTED) {
notification.flags |= Notification.FLAG_CAN_COLORIZE;
} else {
@@ -7059,6 +7087,29 @@ public class NotificationManagerService extends SystemService {
return mPermissionHelper.hasPermission(uid);
}
+ private int getNotificationCount(String pkg, int userId) {
+ int count = 0;
+ synchronized (mNotificationLock) {
+ final int numListSize = mNotificationList.size();
+ for (int i = 0; i < numListSize; i++) {
+ final NotificationRecord existing = mNotificationList.get(i);
+ if (existing.getSbn().getPackageName().equals(pkg)
+ && existing.getSbn().getUserId() == userId) {
+ count++;
+ }
+ }
+ final int numEnqSize = mEnqueuedNotifications.size();
+ for (int i = 0; i < numEnqSize; i++) {
+ final NotificationRecord existing = mEnqueuedNotifications.get(i);
+ if (existing.getSbn().getPackageName().equals(pkg)
+ && existing.getSbn().getUserId() == userId) {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+
protected int getNotificationCount(String pkg, int userId, int excludedId,
String excludedTag) {
int count = 0;
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 632a34e4470d..921233132931 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -430,6 +430,7 @@ class ShortcutPackage extends ShortcutPackageItem {
@NonNull List<ShortcutInfo> changedShortcuts) {
Preconditions.checkArgument(newShortcut.isEnabled(),
"pushDynamicShortcuts() cannot publish disabled shortcuts");
+ ensureShortcutCountBeforePush();
newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
@@ -437,7 +438,7 @@ class ShortcutPackage extends ShortcutPackageItem {
final ShortcutInfo oldShortcut = findShortcutById(newShortcut.getId());
boolean deleted = false;
- if (oldShortcut == null) {
+ if (oldShortcut == null || !oldShortcut.isDynamic()) {
final ShortcutService service = mShortcutUser.mService;
final int maxShortcuts = service.getMaxActivityShortcuts();
@@ -446,18 +447,12 @@ class ShortcutPackage extends ShortcutPackageItem {
final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity());
if (activityShortcuts != null && activityShortcuts.size() > maxShortcuts) {
- Slog.e(TAG, "Error pushing shortcut. There are already "
- + activityShortcuts.size() + " shortcuts, exceeding the " + maxShortcuts
- + " shortcuts limit when pushing the new shortcut " + newShortcut
- + ". Id of shortcuts currently available in system memory are "
- + activityShortcuts.stream().map(ShortcutInfo::getId)
- .collect(Collectors.joining(",", "[", "]")));
- // TODO: This should not have happened. If it does, identify the root cause where
- // possible, otherwise bail-out early to prevent memory issue.
+ // Root cause was discovered in b/233155034, so this should not be happening.
+ service.wtf("Error pushing shortcut. There are already "
+ + activityShortcuts.size() + " shortcuts.");
}
if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) {
// Max has reached. Delete the shortcut with lowest rank.
-
// Sort by isManifestShortcut() and getRank().
Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator);
@@ -473,7 +468,8 @@ class ShortcutPackage extends ShortcutPackageItem {
deleted = deleteDynamicWithId(shortcut.getId(), /* ignoreInvisible =*/ true,
/*ignorePersistedShortcuts=*/ true) != null;
}
- } else {
+ }
+ if (oldShortcut != null) {
// It's an update case.
// Make sure the target is updatable. (i.e. should be mutable.)
oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
@@ -505,6 +501,32 @@ class ShortcutPackage extends ShortcutPackageItem {
return deleted;
}
+ private void ensureShortcutCountBeforePush() {
+ final ShortcutService service = mShortcutUser.mService;
+ // Ensure the total number of shortcuts doesn't exceed the hard limit per app.
+ final int maxShortcutPerApp = service.getMaxAppShortcuts();
+ synchronized (mLock) {
+ final List<ShortcutInfo> appShortcuts = mShortcuts.values().stream().filter(si ->
+ !si.isPinned()).collect(Collectors.toList());
+ if (appShortcuts.size() >= maxShortcutPerApp) {
+ // Max has reached. Removes shortcuts until they fall within the hard cap.
+ // Sort by isManifestShortcut(), isDynamic() and getLastChangedTimestamp().
+ Collections.sort(appShortcuts, mShortcutTypeRankAndTimeComparator);
+
+ while (appShortcuts.size() >= maxShortcutPerApp) {
+ final ShortcutInfo shortcut = appShortcuts.remove(appShortcuts.size() - 1);
+ if (shortcut.isDeclaredInManifest()) {
+ // All shortcuts are manifest shortcuts and cannot be removed.
+ throw new IllegalArgumentException(getPackageName() + " has published "
+ + appShortcuts.size() + " manifest shortcuts across different"
+ + " activities.");
+ }
+ forceDeleteShortcutInner(shortcut.getId());
+ }
+ }
+ }
+ }
+
/**
* Remove all shortcuts that aren't pinned, cached nor dynamic.
*
@@ -1371,6 +1393,61 @@ class ShortcutPackage extends ShortcutPackageItem {
};
/**
+ * To sort by isManifestShortcut(), isDynamic(), getRank() and
+ * getLastChangedTimestamp(). i.e. manifest shortcuts come before non-manifest shortcuts,
+ * dynamic shortcuts come before floating shortcuts, then sort by last changed timestamp.
+ *
+ * This is used to decide which shortcuts to remove when the total number of shortcuts retained
+ * for the app exceeds the limit defined in {@link ShortcutService#getMaxAppShortcuts()}.
+ *
+ * (Note the number of manifest shortcuts is always <= the max number, because if there are
+ * more, ShortcutParser would ignore the rest.)
+ */
+ final Comparator<ShortcutInfo> mShortcutTypeRankAndTimeComparator = (ShortcutInfo a,
+ ShortcutInfo b) -> {
+ if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) {
+ return -1;
+ }
+ if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) {
+ return 1;
+ }
+ if (a.isDynamic() && b.isDynamic()) {
+ return Integer.compare(a.getRank(), b.getRank());
+ }
+ if (a.isDynamic()) {
+ return -1;
+ }
+ if (b.isDynamic()) {
+ return 1;
+ }
+ if (a.isCached() && b.isCached()) {
+ // if both shortcuts are cached, prioritize shortcuts cached by people tile,
+ if (a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+ && !b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+ return -1;
+ } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+ && b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+ return 1;
+ }
+ // followed by bubbles.
+ if (a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+ && !b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+ return -1;
+ } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+ && b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+ return 1;
+ }
+ }
+ if (a.isCached()) {
+ return -1;
+ }
+ if (b.isCached()) {
+ return 1;
+ }
+ return Long.compare(b.getLastChangedTimestamp(), a.getLastChangedTimestamp());
+ };
+
+ /**
* Build a list of shortcuts for each target activity and return as a map. The result won't
* contain "floating" shortcuts because they don't belong on any activities.
*/
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 49831d75db49..a2b2983a8f35 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -181,6 +181,9 @@ public class ShortcutService extends IShortcutService.Stub {
static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;
@VisibleForTesting
+ static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 100;
+
+ @VisibleForTesting
static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
@VisibleForTesting
@@ -257,6 +260,11 @@ public class ShortcutService extends IShortcutService.Stub {
String KEY_MAX_SHORTCUTS = "max_shortcuts";
/**
+ * Key name for the max shortcuts can be retained in system ram per app. (int)
+ */
+ String KEY_MAX_SHORTCUTS_PER_APP = "max_shortcuts_per_app";
+
+ /**
* Key name for icon compression quality, 0-100.
*/
String KEY_ICON_QUALITY = "icon_quality";
@@ -329,11 +337,16 @@ public class ShortcutService extends IShortcutService.Stub {
new SparseArray<>();
/**
- * Max number of dynamic + manifest shortcuts that each application can have at a time.
+ * Max number of dynamic + manifest shortcuts that each activity can have at a time.
*/
private int mMaxShortcuts;
/**
+ * Max number of shortcuts that can exists in system ram for each application.
+ */
+ private int mMaxShortcutsPerApp;
+
+ /**
* Max number of updating API calls that each application can make during the interval.
*/
int mMaxUpdatesPerInterval;
@@ -807,6 +820,9 @@ public class ShortcutService extends IShortcutService.Stub {
mMaxShortcuts = Math.max(0, (int) parser.getLong(
ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY));
+ mMaxShortcutsPerApp = Math.max(0, (int) parser.getLong(
+ ConfigConstants.KEY_MAX_SHORTCUTS_PER_APP, DEFAULT_MAX_SHORTCUTS_PER_APP));
+
final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
? (int) parser.getLong(
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
@@ -1625,7 +1641,7 @@ public class ShortcutService extends IShortcutService.Stub {
return false;
}
int uid = injectGetPackageUid(systemChooser.getPackageName(), UserHandle.USER_SYSTEM);
- return uid == callingUid;
+ return UserHandle.getAppId(uid) == UserHandle.getAppId(callingUid);
}
private void enforceSystemOrShell() {
@@ -1759,6 +1775,13 @@ public class ShortcutService extends IShortcutService.Stub {
}
/**
+ * Return the max number of shortcuts can be retaiend in system ram for each application.
+ */
+ int getMaxAppShortcuts() {
+ return mMaxShortcutsPerApp;
+ }
+
+ /**
* - Sends a notification to LauncherApps
* - Write to file
*/
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f913cef99813..eedb4b0a3bde 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -199,6 +199,7 @@ import com.android.internal.policy.PhoneWindow;
import com.android.internal.policy.TransitionAnimation;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.widget.LockPatternUtils;
import com.android.server.ExtconStateObserver;
import com.android.server.ExtconUEventObserver;
import com.android.server.GestureLauncherService;
@@ -407,6 +408,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
AppOpsManager mAppOpsManager;
PackageManager mPackageManager;
SideFpsEventHandler mSideFpsEventHandler;
+ LockPatternUtils mLockPatternUtils;
private boolean mHasFeatureAuto;
private boolean mHasFeatureWatch;
private boolean mHasFeatureLeanback;
@@ -627,6 +629,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private boolean mLockNowPending = false;
+ // Timeout for showing the keyguard after the screen is on, in case no "ready" is received.
+ private int mKeyguardDrawnTimeout = 1000;
+
private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
@@ -1056,8 +1061,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
synchronized (mLock) {
- // Lock the device after the dream transition has finished.
- mLockAfterAppTransitionFinished = true;
+ // If the setting to lock instantly on power button press is true, then set the flag to
+ // lock after the dream transition has finished.
+ mLockAfterAppTransitionFinished =
+ mLockPatternUtils.getPowerButtonInstantlyLocks(mCurrentUserId);
}
dreamManagerInternal.requestDream();
@@ -1929,6 +1936,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHasFeatureHdmiCec = mPackageManager.hasSystemFeature(FEATURE_HDMI_CEC);
mAccessibilityShortcutController =
new AccessibilityShortcutController(mContext, new Handler(), mCurrentUserId);
+ mLockPatternUtils = new LockPatternUtils(mContext);
mLogger = new MetricsLogger();
mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal
@@ -2156,6 +2164,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
});
+ mKeyguardDrawnTimeout = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_keyguardDrawnTimeout);
mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
new StateCallback() {
@Override
@@ -4761,7 +4771,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final boolean bootCompleted =
LocalServices.getService(SystemServiceManager.class).isBootCompleted();
// Set longer timeout if it has not booted yet to prevent showing empty window.
- return bootCompleted ? 1000 : 5000;
+ return bootCompleted ? mKeyguardDrawnTimeout : 5000;
}
// Called on the DisplayManager's DisplayPowerController thread.
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 3baaa9d44019..45d2e3c89245 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -29,6 +29,7 @@ import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService;
import com.android.server.UiThread;
import com.android.server.policy.WindowManagerPolicy.OnKeyguardExitResult;
+import com.android.server.wm.EventLogTags;
import java.io.PrintWriter;
@@ -257,6 +258,11 @@ public class KeyguardServiceDelegate {
public void setOccluded(boolean isOccluded, boolean animate, boolean notify) {
if (mKeyguardService != null && notify) {
if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ") animate=" + animate);
+ EventLogTags.writeWmSetKeyguardOccluded(
+ isOccluded ? 1 : 0,
+ animate ? 1 : 0,
+ 0 /* transit */,
+ "setOccluded");
mKeyguardService.setOccluded(isOccluded, animate);
}
mKeyguardState.occluded = isOccluded;
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index b4b8cf9a9eab..43fb44ca02af 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -169,6 +169,7 @@ import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.procstats.IProcessStats;
import com.android.internal.app.procstats.ProcessStats;
+import com.android.internal.app.procstats.StatsEventOutput;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BinderCallsStats.ExportedCallStat;
import com.android.internal.os.KernelAllocationStats;
@@ -612,12 +613,19 @@ public class StatsPullAtomService extends SystemService {
}
case FrameworkStatsLog.PROC_STATS:
synchronized (mProcStatsLock) {
- return pullProcStatsLocked(ProcessStats.REPORT_ALL, atomTag, data);
+ return pullProcStatsLocked(atomTag, data);
}
case FrameworkStatsLog.PROC_STATS_PKG_PROC:
synchronized (mProcStatsLock) {
- return pullProcStatsLocked(ProcessStats.REPORT_PKG_PROC_STATS, atomTag,
- data);
+ return pullProcStatsLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.PROCESS_STATE:
+ synchronized (mProcStatsLock) {
+ return pullProcessStateLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.PROCESS_ASSOCIATION:
+ synchronized (mProcStatsLock) {
+ return pullProcessAssociationLocked(atomTag, data);
}
case FrameworkStatsLog.DISK_IO:
synchronized (mDiskIoLock) {
@@ -890,6 +898,8 @@ public class StatsPullAtomService extends SystemService {
registerNumFacesEnrolled();
registerProcStats();
registerProcStatsPkgProc();
+ registerProcessState();
+ registerProcessAssociation();
registerDiskIO();
registerPowerProfile();
registerProcessCpuTime();
@@ -2870,59 +2880,138 @@ public class StatsPullAtomService extends SystemService {
);
}
- private int pullProcStatsLocked(int section, int atomTag, List<StatsEvent> pulledData) {
+ private void registerProcessState() {
+ int tagId = FrameworkStatsLog.PROCESS_STATE;
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl);
+ }
+
+ private void registerProcessAssociation() {
+ int tagId = FrameworkStatsLog.PROCESS_ASSOCIATION;
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl);
+ }
+
+ @GuardedBy("mProcStatsLock")
+ private ProcessStats getStatsFromProcessStatsService(int atomTag) {
IProcessStats processStatsService = getIProcessStatsService();
if (processStatsService == null) {
- return StatsManager.PULL_SKIP;
+ return null;
}
-
final long token = Binder.clearCallingIdentity();
try {
// force procstats to flush & combine old files into one store
- long lastHighWaterMark = readProcStatsHighWaterMark(section);
-
- ProtoOutputStream[] protoStreams = new ProtoOutputStream[MAX_PROCSTATS_SHARDS];
- for (int i = 0; i < protoStreams.length; i++) {
- protoStreams[i] = new ProtoOutputStream();
- }
-
+ long lastHighWaterMark = readProcStatsHighWaterMark(atomTag);
ProcessStats procStats = new ProcessStats(false);
// Force processStatsService to aggregate all in-storage and in-memory data.
- long highWaterMark = processStatsService.getCommittedStatsMerged(
- lastHighWaterMark, section, true, null, procStats);
- procStats.dumpAggregatedProtoForStatsd(protoStreams, MAX_PROCSTATS_RAW_SHARD_SIZE);
-
- for (int i = 0; i < protoStreams.length; i++) {
- byte[] bytes = protoStreams[i].getBytes(); // cache the value
- if (bytes.length > 0) {
- pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, bytes,
- // This is a shard ID, and is specified in the metric definition to be
- // a dimension. This will result in statsd using RANDOM_ONE_SAMPLE to
- // keep all the shards, as it thinks each shard is a different dimension
- // of data.
- i));
- }
- }
-
- new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + lastHighWaterMark)
+ long highWaterMark =
+ processStatsService.getCommittedStatsMerged(
+ lastHighWaterMark,
+ ProcessStats.REPORT_ALL, // ignored since committedStats below is null.
+ true,
+ null, // committedStats
+ procStats);
+ new File(
+ mBaseDir.getAbsolutePath()
+ + "/"
+ + highWaterMarkFilePrefix(atomTag)
+ + "_"
+ + lastHighWaterMark)
.delete();
- new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + highWaterMark)
+ new File(
+ mBaseDir.getAbsolutePath()
+ + "/"
+ + highWaterMarkFilePrefix(atomTag)
+ + "_"
+ + highWaterMark)
.createNewFile();
+ return procStats;
} catch (RemoteException | IOException e) {
Slog.e(TAG, "Getting procstats failed: ", e);
- return StatsManager.PULL_SKIP;
+ return null;
} finally {
Binder.restoreCallingIdentity(token);
}
+ }
+
+ @GuardedBy("mProcStatsLock")
+ private int pullProcStatsLocked(int atomTag, List<StatsEvent> pulledData) {
+ ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
+ if (procStats == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ ProtoOutputStream[] protoStreams = new ProtoOutputStream[MAX_PROCSTATS_SHARDS];
+ for (int i = 0; i < protoStreams.length; i++) {
+ protoStreams[i] = new ProtoOutputStream();
+ }
+ procStats.dumpAggregatedProtoForStatsd(protoStreams, MAX_PROCSTATS_RAW_SHARD_SIZE);
+ for (int i = 0; i < protoStreams.length; i++) {
+ byte[] bytes = protoStreams[i].getBytes(); // cache the value
+ if (bytes.length > 0) {
+ pulledData.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ bytes,
+ // This is a shard ID, and is specified in the metric definition to
+ // be
+ // a dimension. This will result in statsd using RANDOM_ONE_SAMPLE
+ // to
+ // keep all the shards, as it thinks each shard is a different
+ // dimension
+ // of data.
+ i));
+ }
+ }
+ return StatsManager.PULL_SUCCESS;
+ }
+
+ @GuardedBy("mProcStatsLock")
+ private int pullProcessStateLocked(int atomTag, List<StatsEvent> pulledData) {
+ ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
+ if (procStats == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ procStats.dumpProcessState(atomTag, new StatsEventOutput(pulledData));
+ return StatsManager.PULL_SUCCESS;
+ }
+
+ @GuardedBy("mProcStatsLock")
+ private int pullProcessAssociationLocked(int atomTag, List<StatsEvent> pulledData) {
+ ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
+ if (procStats == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ procStats.dumpProcessAssociation(atomTag, new StatsEventOutput(pulledData));
return StatsManager.PULL_SUCCESS;
}
+ private String highWaterMarkFilePrefix(int atomTag) {
+ // For backward compatibility, use the legacy ProcessStats enum value as the prefix for
+ // PROC_STATS and PROC_STATS_PKG_PROC.
+ if (atomTag == FrameworkStatsLog.PROC_STATS) {
+ return String.valueOf(ProcessStats.REPORT_ALL);
+ }
+ if (atomTag == FrameworkStatsLog.PROC_STATS_PKG_PROC) {
+ return String.valueOf(ProcessStats.REPORT_PKG_PROC_STATS);
+ }
+ return "atom-" + atomTag;
+ }
+
// read high watermark for section
- private long readProcStatsHighWaterMark(int section) {
+ private long readProcStatsHighWaterMark(int atomTag) {
try {
- File[] files = mBaseDir.listFiles((d, name) -> {
- return name.toLowerCase().startsWith(String.valueOf(section) + '_');
- });
+ File[] files =
+ mBaseDir.listFiles(
+ (d, name) -> {
+ return name.toLowerCase()
+ .startsWith(highWaterMarkFilePrefix(atomTag) + '_');
+ });
if (files == null || files.length == 0) {
return 0;
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index ab7292d49c7d..6e342939c95a 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -152,6 +152,13 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
static final long REQUEST_LISTENING_MUST_MATCH_PACKAGE = 172251878L;
+ /**
+ * @hide
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ static final long REQUEST_LISTENING_OTHER_USER_NOOP = 242194868L;
+
private final Context mContext;
private final Handler mHandler = new Handler();
@@ -1859,7 +1866,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
// Check current user
if (userId != currentUser) {
- throw new IllegalArgumentException("User " + userId + " is not the current user.");
+ if (CompatChanges.isChangeEnabled(REQUEST_LISTENING_OTHER_USER_NOOP, callingUid)) {
+ return;
+ } else {
+ throw new IllegalArgumentException(
+ "User " + userId + " is not the current user.");
+ }
}
}
if (mBar != null) {
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 7489f80946eb..7c9244e39e67 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -696,6 +696,8 @@ class ActivityClientController extends IActivityClientController.Stub {
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
if (r != null) {
+ EventLogTags.writeWmSetRequestedOrientation(requestedOrientation,
+ r.shortComponentName);
r.setRequestedOrientation(requestedOrientation);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 8aca912999cc..b946e7e06044 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -341,6 +341,7 @@ import android.window.TransitionInfo.AnimationOptions;
import android.window.WindowContainerToken;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
@@ -503,7 +504,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
private RemoteTransition mPendingRemoteTransition;
ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
+ @GuardedBy("this")
ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
+ /** @see android.content.Context#BIND_ADJUST_WITH_ACTIVITY */
+ volatile boolean mVisibleForServiceConnection;
UriPermissionOwner uriPermissions; // current special URI access perms.
WindowProcessController app; // if non-null, hosting application
private State mState; // current state we are in
@@ -553,7 +557,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
long lastLaunchTime; // time of last launch of this activity
ComponentName requestedVrComponent; // the requested component for handling VR mode.
- boolean inHistory; // are we in the history task?
+ /** Whether this activity is reachable from hierarchy. */
+ volatile boolean inHistory;
final ActivityTaskSupervisor mTaskSupervisor;
final RootWindowContainer mRootWindowContainer;
@@ -1482,6 +1487,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mLastReportedMultiWindowMode = inPictureInPictureMode;
ensureActivityConfiguration(0 /* globalChanges */, PRESERVE_WINDOWS,
true /* ignoreVisibility */);
+ if (inPictureInPictureMode && findMainWindow() == null) {
+ // Prevent malicious app entering PiP without valid WindowState, which can in turn
+ // result a non-touchable PiP window since the InputConsumer for PiP requires it.
+ EventLog.writeEvent(0x534e4554, "265293293", -1, "");
+ removeImmediately();
+ }
}
}
@@ -1904,7 +1915,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
- static @Nullable ActivityRecord forTokenLocked(IBinder token) {
+ /** Gets the corresponding record by the token. Note that it may not exist in the hierarchy. */
+ @Nullable
+ static ActivityRecord forToken(IBinder token) {
if (token == null) return null;
final Token activityToken;
try {
@@ -1913,7 +1926,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
Slog.w(TAG, "Bad activity token: " + token, e);
return null;
}
- final ActivityRecord r = activityToken.mActivityRef.get();
+ return activityToken.mActivityRef.get();
+ }
+
+ static @Nullable ActivityRecord forTokenLocked(IBinder token) {
+ final ActivityRecord r = forToken(token);
return r == null || r.getRootTask() == null ? null : r;
}
@@ -4036,17 +4053,32 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mDisplayContent.getDisplayPolicy().removeRelaunchingApp(this);
}
+ ActivityServiceConnectionsHolder getOrCreateServiceConnectionsHolder() {
+ synchronized (this) {
+ if (mServiceConnectionsHolder == null) {
+ mServiceConnectionsHolder = new ActivityServiceConnectionsHolder(this);
+ }
+ return mServiceConnectionsHolder;
+ }
+ }
+
/**
* Perform clean-up of service connections in an activity record.
*/
private void cleanUpActivityServices() {
- if (mServiceConnectionsHolder == null) {
- return;
+ synchronized (this) {
+ if (mServiceConnectionsHolder == null) {
+ return;
+ }
+ // Throw away any services that have been bound by this activity.
+ mServiceConnectionsHolder.disconnectActivityFromServices();
+ // This activity record is removing, make sure not to disconnect twice.
+ mServiceConnectionsHolder = null;
}
- // Throw away any services that have been bound by this activity.
- mServiceConnectionsHolder.disconnectActivityFromServices();
- // This activity record is removing, make sure not to disconnect twice.
- mServiceConnectionsHolder = null;
+ }
+
+ private void updateVisibleForServiceConnection() {
+ mVisibleForServiceConnection = mVisibleRequested || mState == RESUMED || mState == PAUSING;
}
/**
@@ -5139,6 +5171,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
taskFragment.onActivityVisibleRequestedChanged();
}
setInsetsFrozen(!visible);
+ updateVisibleForServiceConnection();
if (app != null) {
mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */);
}
@@ -5617,6 +5650,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return;
}
}
+ updateVisibleForServiceConnection();
if (app != null) {
mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */);
}
@@ -7699,25 +7733,35 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
/**
* Returns the requested {@link Configuration.Orientation} for the current activity.
+ */
+ @Configuration.Orientation
+ @Override
+ int getRequestedConfigurationOrientation(boolean forDisplay) {
+ return getRequestedConfigurationOrientation(forDisplay, getOverrideOrientation());
+ }
+
+ /**
+ * Returns the requested {@link Configuration.Orientation} for the requested
+ * {@link ActivityInfo.ScreenOrientation}.
*
- * <p>When The current orientation is set to {@link SCREEN_ORIENTATION_BEHIND} it returns the
- * requested orientation for the activity below which is the first activity with an explicit
+ * <p>When the current screen orientation is set to {@link SCREEN_ORIENTATION_BEHIND} it returns
+ * the requested orientation for the activity below which is the first activity with an explicit
* (different from {@link SCREEN_ORIENTATION_UNSET}) orientation which is not {@link
* SCREEN_ORIENTATION_BEHIND}.
*/
@Configuration.Orientation
- @Override
- int getRequestedConfigurationOrientation(boolean forDisplay) {
+ int getRequestedConfigurationOrientation(boolean forDisplay,
+ @ActivityInfo.ScreenOrientation int requestedOrientation) {
if (mLetterboxUiController.hasInheritedOrientation()) {
final RootDisplayArea root = getRootDisplayArea();
if (forDisplay && root != null && root.isOrientationDifferentFromDisplay()) {
- return ActivityInfo.reverseOrientation(
+ return reverseConfigurationOrientation(
mLetterboxUiController.getInheritedOrientation());
} else {
return mLetterboxUiController.getInheritedOrientation();
}
}
- if (task != null && getOverrideOrientation() == SCREEN_ORIENTATION_BEHIND) {
+ if (task != null && requestedOrientation == SCREEN_ORIENTATION_BEHIND) {
// We use Task here because we want to be consistent with what happens in
// multi-window mode where other tasks orientations are ignored.
final ActivityRecord belowCandidate = task.getActivity(
@@ -7728,7 +7772,23 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return belowCandidate.getRequestedConfigurationOrientation(forDisplay);
}
}
- return super.getRequestedConfigurationOrientation(forDisplay);
+ return super.getRequestedConfigurationOrientation(forDisplay, requestedOrientation);
+ }
+
+ /**
+ * Returns the reversed configuration orientation.
+ * @hide
+ */
+ @Configuration.Orientation
+ public static int reverseConfigurationOrientation(@Configuration.Orientation int orientation) {
+ switch (orientation) {
+ case ORIENTATION_LANDSCAPE:
+ return ORIENTATION_PORTRAIT;
+ case ORIENTATION_PORTRAIT:
+ return ORIENTATION_LANDSCAPE;
+ default:
+ return orientation;
+ }
}
/**
@@ -7774,6 +7834,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (mLetterboxUiController.shouldIgnoreRequestedOrientation(requestedOrientation)) {
return;
}
+ // This is necessary in order to avoid going into size compat mode when the orientation
+ // change request comes from the app
+ if (mWmService.mLetterboxConfiguration
+ .isSizeCompatModeDisabledAfterOrientationChangeFromApp()
+ && getRequestedConfigurationOrientation(false, requestedOrientation)
+ != getRequestedConfigurationOrientation(false /*forDisplay */)) {
+ // Do not change the requested configuration now, because this will be done when setting
+ // the orientation below with the new mCompatDisplayInsets
+ clearSizeCompatModeAttributes();
+ }
+ ProtoLog.v(WM_DEBUG_ORIENTATION,
+ "Setting requested orientation %s for %s",
+ ActivityInfo.screenOrientationToString(requestedOrientation), this);
setOrientation(requestedOrientation, this);
// Push the new configuration to the requested app in case where it's not pushed, e.g. when
@@ -7880,6 +7953,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/**
+ * @return The {@code true} if the current instance has {@link mCompatDisplayInsets} without
+ * considering the inheritance implemented in {@link #getCompatDisplayInsets()}
+ */
+ boolean hasCompatDisplayInsetsWithoutInheritance() {
+ return mCompatDisplayInsets != null;
+ }
+
+ /**
* @return {@code true} if this activity is in size compatibility mode that uses the different
* density than its parent or its bounds don't fit in parent naturally.
*/
@@ -7887,7 +7968,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (mInSizeCompatModeForBounds) {
return true;
}
- if (mCompatDisplayInsets == null || !shouldCreateCompatDisplayInsets()
+ if (getCompatDisplayInsets() == null || !shouldCreateCompatDisplayInsets()
// The orientation is different from parent when transforming.
|| isFixedRotationTransforming()) {
return false;
@@ -7937,11 +8018,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return false;
}
}
- // Activity should be resizable if the task is.
- final boolean isResizeable = task != null
- ? task.isResizeable() || isResizeable()
- : isResizeable();
- return !isResizeable && (info.isFixedOrientation() || hasFixedAspectRatio())
+ return !isResizeable() && (info.isFixedOrientation() || hasFixedAspectRatio())
// The configuration of non-standard type should be enforced by system.
// {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} is set when this activity is
// added to a task, but this function is called when resolving the launch params, at
@@ -7958,11 +8035,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
private void updateCompatDisplayInsets() {
- if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
- mCompatDisplayInsets = mLetterboxUiController.getInheritedCompatDisplayInsets();
- return;
- }
- if (mCompatDisplayInsets != null || !shouldCreateCompatDisplayInsets()) {
+ if (getCompatDisplayInsets() != null || !shouldCreateCompatDisplayInsets()) {
// The override configuration is set only once in size compatibility mode.
return;
}
@@ -7980,9 +8053,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// The smallest screen width is the short side of screen bounds. Because the bounds
// and density won't be changed, smallestScreenWidthDp is also fixed.
overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp;
- // TODO(b/264276741): Check whether the runtime orietnation request is fixed rather than
- // the manifest orientation which may be obsolete.
- if (info.isFixedOrientation()) {
+ if (ActivityInfo.isFixedOrientation(getOverrideOrientation())) {
// lock rotation too. When in size-compat, onConfigurationChanged will watch for and
// apply runtime rotation changes.
overrideConfig.windowConfiguration.setRotation(
@@ -7995,19 +8066,28 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mDisplayContent, this, mLetterboxBoundsForFixedOrientationAndAspectRatio);
}
- @VisibleForTesting
- void clearSizeCompatMode() {
- final float lastSizeCompatScale = mSizeCompatScale;
+ private void clearSizeCompatModeAttributes() {
mInSizeCompatModeForBounds = false;
mSizeCompatScale = 1f;
mSizeCompatBounds = null;
mCompatDisplayInsets = null;
+ }
+
+ @VisibleForTesting
+ void clearSizeCompatMode() {
+ final float lastSizeCompatScale = mSizeCompatScale;
+ clearSizeCompatModeAttributes();
if (mSizeCompatScale != lastSizeCompatScale) {
forAllWindows(WindowState::updateGlobalScale, false /* traverseTopToBottom */);
}
-
// Clear config override in #updateCompatDisplayInsets().
- onRequestedOverrideConfigurationChanged(EMPTY);
+ final int activityType = getActivityType();
+ final Configuration overrideConfig = getRequestedOverrideConfiguration();
+ overrideConfig.unset();
+ // Keep the activity type which was set when attaching to a task to prevent leaving it
+ // undefined.
+ overrideConfig.windowConfiguration.setActivityType(activityType);
+ onRequestedOverrideConfigurationChanged(overrideConfig);
}
@Override
@@ -8025,9 +8105,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
float getCompatScale() {
- if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
- return mLetterboxUiController.getInheritedSizeCompatScale();
- }
return hasSizeCompatBounds() ? mSizeCompatScale : super.getCompatScale();
}
@@ -8070,9 +8147,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (isFixedOrientationLetterboxAllowed) {
resolveFixedOrientationConfiguration(newParentConfiguration);
}
-
- if (mCompatDisplayInsets != null) {
- resolveSizeCompatModeConfiguration(newParentConfiguration);
+ final CompatDisplayInsets compatDisplayInsets = getCompatDisplayInsets();
+ if (compatDisplayInsets != null) {
+ resolveSizeCompatModeConfiguration(newParentConfiguration, compatDisplayInsets);
} else if (inMultiWindowMode() && !isFixedOrientationLetterboxAllowed) {
// We ignore activities' requested orientation in multi-window modes. They may be
// taken into consideration in resolveFixedOrientationConfiguration call above.
@@ -8089,7 +8166,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
resolveAspectRatioRestriction(newParentConfiguration);
}
- if (isFixedOrientationLetterboxAllowed || mCompatDisplayInsets != null
+ if (isFixedOrientationLetterboxAllowed || compatDisplayInsets != null
// In fullscreen, can be letterboxed for aspect ratio.
|| !inMultiWindowMode()) {
updateResolvedBoundsPosition(newParentConfiguration);
@@ -8097,7 +8174,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean isIgnoreOrientationRequest = mDisplayContent != null
&& mDisplayContent.getIgnoreOrientationRequest();
- if (mCompatDisplayInsets == null // for size compat mode set in updateCompatDisplayInsets
+ if (compatDisplayInsets == null
+ // for size compat mode set in updateCompatDisplayInsets
// Fixed orientation letterboxing is possible on both large screen devices
// with ignoreOrientationRequest enabled and on phones in split screen even with
// ignoreOrientationRequest disabled.
@@ -8143,7 +8221,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
info.neverSandboxDisplayApis(sConstrainDisplayApisConfig),
info.alwaysSandboxDisplayApis(sConstrainDisplayApisConfig),
!matchParentBounds(),
- mCompatDisplayInsets != null,
+ compatDisplayInsets != null,
shouldCreateCompatDisplayInsets());
}
resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
@@ -8155,7 +8233,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
/**
* @return The orientation to use to understand if reachability is enabled.
*/
- @ActivityInfo.ScreenOrientation
+ @Configuration.Orientation
int getOrientationForReachability() {
return mLetterboxUiController.hasInheritedLetterboxBehavior()
? mLetterboxUiController.getInheritedOrientation()
@@ -8442,8 +8520,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|| orientationRespectedWithInsets)) {
return;
}
+ final CompatDisplayInsets compatDisplayInsets = getCompatDisplayInsets();
- if (mCompatDisplayInsets != null && !mCompatDisplayInsets.mIsInFixedOrientationLetterbox) {
+ if (compatDisplayInsets != null && !compatDisplayInsets.mIsInFixedOrientationLetterbox) {
// App prefers to keep its original size.
// If the size compat is from previous fixed orientation letterboxing, we may want to
// have fixed orientation letterbox again, otherwise it will show the size compat
@@ -8498,9 +8577,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingBoundsWithInsets,
containingBounds, desiredAspectRatio);
- if (mCompatDisplayInsets != null) {
- mCompatDisplayInsets.getBoundsByRotation(
- mTmpBounds, newParentConfig.windowConfiguration.getRotation());
+ if (compatDisplayInsets != null) {
+ compatDisplayInsets.getBoundsByRotation(mTmpBounds,
+ newParentConfig.windowConfiguration.getRotation());
if (resolvedBounds.width() != mTmpBounds.width()
|| resolvedBounds.height() != mTmpBounds.height()) {
// The app shouldn't be resized, we only do fixed orientation letterboxing if the
@@ -8514,7 +8593,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Calculate app bounds using fixed orientation bounds because they will be needed later
// for comparison with size compat app bounds in {@link resolveSizeCompatModeConfiguration}.
getTaskFragment().computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
- newParentConfig, mCompatDisplayInsets);
+ newParentConfig, compatDisplayInsets);
mLetterboxBoundsForFixedOrientationAndAspectRatio = new Rect(resolvedBounds);
}
@@ -8550,7 +8629,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* Resolves consistent screen configuration for orientation and rotation changes without
* inheriting the parent bounds.
*/
- private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
+ private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration,
+ @NonNull CompatDisplayInsets compatDisplayInsets) {
final Configuration resolvedConfig = getResolvedOverrideConfiguration();
final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
@@ -8571,13 +8651,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
? requestedOrientation
// We should use the original orientation of the activity when possible to avoid
// forcing the activity in the opposite orientation.
- : mCompatDisplayInsets.mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
- ? mCompatDisplayInsets.mOriginalRequestedOrientation
+ : compatDisplayInsets.mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
+ ? compatDisplayInsets.mOriginalRequestedOrientation
: newParentConfiguration.orientation;
int rotation = newParentConfiguration.windowConfiguration.getRotation();
final boolean isFixedToUserRotation = mDisplayContent == null
|| mDisplayContent.getDisplayRotation().isFixedToUserRotation();
- if (!isFixedToUserRotation && !mCompatDisplayInsets.mIsFloating) {
+ if (!isFixedToUserRotation && !compatDisplayInsets.mIsFloating) {
// Use parent rotation because the original display can be rotated.
resolvedConfig.windowConfiguration.setRotation(rotation);
} else {
@@ -8593,11 +8673,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// rely on them to contain the original and unchanging width and height of the app.
final Rect containingAppBounds = new Rect();
final Rect containingBounds = mTmpBounds;
- mCompatDisplayInsets.getContainerBounds(containingAppBounds, containingBounds, rotation,
+ compatDisplayInsets.getContainerBounds(containingAppBounds, containingBounds, rotation,
orientation, orientationRequested, isFixedToUserRotation);
resolvedBounds.set(containingBounds);
// The size of floating task is fixed (only swap), so the aspect ratio is already correct.
- if (!mCompatDisplayInsets.mIsFloating) {
+ if (!compatDisplayInsets.mIsFloating) {
mIsAspectRatioApplied =
applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
}
@@ -8606,7 +8686,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// are calculated in compat container space. The actual position on screen will be applied
// later, so the calculation is simpler that doesn't need to involve offset from parent.
getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
- mCompatDisplayInsets);
+ compatDisplayInsets);
// Use current screen layout as source because the size of app is independent to parent.
resolvedConfig.screenLayout = TaskFragment.computeScreenLayoutOverride(
getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
@@ -8641,14 +8721,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Calculates the scale the size compatibility bounds into the region which is available
// to application.
- final int contentW = resolvedAppBounds.width();
- final int contentH = resolvedAppBounds.height();
- final int viewportW = containerAppBounds.width();
- final int viewportH = containerAppBounds.height();
final float lastSizeCompatScale = mSizeCompatScale;
- // Only allow to scale down.
- mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
- ? 1f : Math.min((float) viewportW / contentW, (float) viewportH / contentH);
+ updateSizeCompatScale(resolvedAppBounds, containerAppBounds);
+
final int containerTopInset = containerAppBounds.top - containerBounds.top;
final boolean topNotAligned =
containerTopInset != resolvedAppBounds.top - resolvedBounds.top;
@@ -8688,6 +8763,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
isInSizeCompatModeForBounds(resolvedAppBounds, containerAppBounds);
}
+ void updateSizeCompatScale(Rect resolvedAppBounds, Rect containerAppBounds) {
+ // Only allow to scale down.
+ mSizeCompatScale = mLetterboxUiController.findOpaqueNotFinishingActivityBelow()
+ .map(activityRecord -> activityRecord.mSizeCompatScale)
+ .orElseGet(() -> {
+ final int contentW = resolvedAppBounds.width();
+ final int contentH = resolvedAppBounds.height();
+ final int viewportW = containerAppBounds.width();
+ final int viewportH = containerAppBounds.height();
+ return (contentW <= viewportW && contentH <= viewportH) ? 1f : Math.min(
+ (float) viewportW / contentW, (float) viewportH / contentH);
+ });
+ }
+
private boolean isInSizeCompatModeForBounds(final Rect appBounds, final Rect containerBounds) {
if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
// To avoid wrong app behaviour, we decided to disable SCM when a translucent activity
@@ -8750,10 +8839,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
public Rect getBounds() {
- if (mSizeCompatBounds != null) {
- return mSizeCompatBounds;
- }
- return super.getBounds();
+ // TODO(b/268458693): Refactor configuration inheritance in case of translucent activities
+ final Rect superBounds = super.getBounds();
+ return mLetterboxUiController.findOpaqueNotFinishingActivityBelow()
+ .map(ActivityRecord::getBounds)
+ .orElseGet(() -> {
+ if (mSizeCompatBounds != null) {
+ return mSizeCompatBounds;
+ }
+ return superBounds;
+ });
}
@Override
@@ -8778,7 +8873,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Max bounds should be sandboxed when an activity should have compatDisplayInsets, and it
// will keep the same bounds and screen configuration when it was first launched regardless
// how its parent window changes, so that the sandbox API will provide a consistent result.
- if (mCompatDisplayInsets != null || shouldCreateCompatDisplayInsets()) {
+ if (getCompatDisplayInsets() != null || shouldCreateCompatDisplayInsets()) {
return true;
}
@@ -8820,7 +8915,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mTransitionController.collect(this);
}
}
- if (mCompatDisplayInsets != null) {
+ if (getCompatDisplayInsets() != null) {
Configuration overrideConfig = getRequestedOverrideConfiguration();
// Adapt to changes in orientation locking. The app is still non-resizable, but
// it can change which orientation is fixed. If the fixed orientation changes,
@@ -8850,6 +8945,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final boolean wasInPictureInPicture = inPinnedWindowingMode();
final DisplayContent display = mDisplayContent;
+ final int activityType = getActivityType();
if (wasInPictureInPicture && attachedToProcess() && display != null) {
// If the PIP activity is changing to fullscreen with display orientation change, the
// fixed rotation will take effect that requires to send fixed rotation adjustments
@@ -8874,6 +8970,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
} else {
super.onConfigurationChanged(newParentConfig);
}
+ if (activityType != ACTIVITY_TYPE_UNDEFINED
+ && activityType != getActivityType()) {
+ Slog.w(TAG, "Can't change activity type once set: " + this
+ + " activityType=" + activityTypeToString(getActivityType()));
+ }
// Configuration's equality doesn't consider seq so if only seq number changes in resolved
// override configuration. Therefore ConfigurationContainer doesn't change merged override
@@ -8896,7 +8997,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (mVisibleRequested) {
// It may toggle the UI for user to restart the size compatibility mode activity.
display.handleActivitySizeCompatModeIfNeeded(this);
- } else if (mCompatDisplayInsets != null && !visibleIgnoringKeyguard
+ } else if (getCompatDisplayInsets() != null && !visibleIgnoringKeyguard
&& (app == null || !app.hasVisibleActivities())) {
// visibleIgnoringKeyguard is checked to avoid clearing mCompatDisplayInsets during
// displays change. Displays are turned off during the change so mVisibleRequested
diff --git a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
index 0859d40c0fd1..5f56af7fd4e0 100644
--- a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
+++ b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
@@ -16,14 +16,14 @@
package com.android.server.wm;
-import static com.android.server.wm.ActivityRecord.State.PAUSING;
-import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import android.util.ArraySet;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -38,8 +38,6 @@ import java.util.function.Consumer;
*/
public class ActivityServiceConnectionsHolder<T> {
- private final ActivityTaskManagerService mService;
-
/** The activity the owns this service connection object. */
private final ActivityRecord mActivity;
@@ -49,19 +47,19 @@ public class ActivityServiceConnectionsHolder<T> {
* on the WM side since we don't perform operations on the object. Mainly here for communication
* and booking with the AM side.
*/
+ @GuardedBy("mActivity")
private ArraySet<T> mConnections;
/** Whether all connections of {@link #mActivity} are being removed. */
private volatile boolean mIsDisconnecting;
- ActivityServiceConnectionsHolder(ActivityTaskManagerService service, ActivityRecord activity) {
- mService = service;
+ ActivityServiceConnectionsHolder(ActivityRecord activity) {
mActivity = activity;
}
/** Adds a connection record that the activity has bound to a specific service. */
public void addConnection(T c) {
- synchronized (mService.mGlobalLock) {
+ synchronized (mActivity) {
if (mIsDisconnecting) {
// This is unlikely to happen because the caller should create a new holder.
if (DEBUG_CLEANUP) {
@@ -79,7 +77,7 @@ public class ActivityServiceConnectionsHolder<T> {
/** Removed a connection record between the activity and a specific service. */
public void removeConnection(T c) {
- synchronized (mService.mGlobalLock) {
+ synchronized (mActivity) {
if (mConnections == null) {
return;
}
@@ -90,20 +88,18 @@ public class ActivityServiceConnectionsHolder<T> {
}
}
+ /** @see android.content.Context#BIND_ADJUST_WITH_ACTIVITY */
public boolean isActivityVisible() {
- synchronized (mService.mGlobalLock) {
- return mActivity.isVisibleRequested() || mActivity.isState(RESUMED, PAUSING);
- }
+ return mActivity.mVisibleForServiceConnection;
}
public int getActivityPid() {
- synchronized (mService.mGlobalLock) {
- return mActivity.hasProcess() ? mActivity.app.getPid() : -1;
- }
+ final WindowProcessController wpc = mActivity.app;
+ return wpc != null ? wpc.getPid() : -1;
}
public void forEachConnection(Consumer<T> consumer) {
- synchronized (mService.mGlobalLock) {
+ synchronized (mActivity) {
if (mConnections == null || mConnections.isEmpty()) {
return;
}
@@ -118,6 +114,7 @@ public class ActivityServiceConnectionsHolder<T> {
* general, this method is used to clean up if the activity didn't unbind services before it
* is destroyed.
*/
+ @GuardedBy("mActivity")
void disconnectActivityFromServices() {
if (mConnections == null || mConnections.isEmpty() || mIsDisconnecting) {
return;
@@ -130,16 +127,14 @@ public class ActivityServiceConnectionsHolder<T> {
// still in the message queue, so keep the reference of {@link #mConnections} to make sure
// the connection list is up-to-date.
mIsDisconnecting = true;
- mService.mH.post(() -> {
- mService.mAmInternal.disconnectActivityFromServices(this);
+ mActivity.mAtmService.mH.post(() -> {
+ mActivity.mAtmService.mAmInternal.disconnectActivityFromServices(this);
mIsDisconnecting = false;
});
}
public void dump(PrintWriter pw, String prefix) {
- synchronized (mService.mGlobalLock) {
- pw.println(prefix + "activity=" + mActivity);
- }
+ pw.println(prefix + "activity=" + mActivity);
}
/** Used by {@link ActivityRecord#dump}. */
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 861961599ada..c527310abb14 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -6000,18 +6000,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public ActivityServiceConnectionsHolder getServiceConnectionsHolder(IBinder token) {
- synchronized (mGlobalLock) {
- final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
- if (r == null) {
- return null;
- }
- if (r.mServiceConnectionsHolder == null) {
- r.mServiceConnectionsHolder = new ActivityServiceConnectionsHolder(
- ActivityTaskManagerService.this, r);
- }
-
- return r.mServiceConnectionsHolder;
+ final ActivityRecord r = ActivityRecord.forToken(token);
+ if (r == null || !r.inHistory) {
+ return null;
}
+ return r.getOrCreateServiceConnectionsHolder();
}
@Override
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index 5e44d6c72bca..e91c9d427c80 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -41,7 +41,8 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
// Desktop mode feature flag.
static final boolean DESKTOP_MODE_SUPPORTED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
+ "persist.wm.debug.desktop_mode", false) || SystemProperties.getBoolean(
+ "persist.wm.debug.desktop_mode_2", false);
// Override default freeform task width when desktop mode is enabled. In dips.
private static final int DESKTOP_MODE_DEFAULT_WIDTH_DP = SystemProperties.getInt(
"persist.wm.debug.desktop_mode.default_width", 840);
@@ -79,8 +80,8 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
appendLog("not in bounds phase, skipping");
return RESULT_SKIP;
}
- if (!task.inFreeformWindowingMode()) {
- appendLog("not a freeform task, skipping");
+ if (!task.isActivityTypeStandard()) {
+ appendLog("not standard activity type, skipping");
return RESULT_SKIP;
}
if (!currentParams.mBounds.isEmpty()) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b0eecebc7d79..ec355b73a7be 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4505,24 +4505,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
@VisibleForTesting
SurfaceControl computeImeParent() {
- if (mImeLayeringTarget != null) {
- // Ensure changing the IME parent when the layering target that may use IME has
- // became to the input target for preventing IME flickers.
- // Note that:
- // 1) For the imeLayeringTarget that may not use IME but requires IME on top
- // of it (e.g. an overlay window with NOT_FOCUSABLE|ALT_FOCUSABLE_IM flags), we allow
- // it to re-parent the IME on top the display to keep the legacy behavior.
- // 2) Even though the starting window won't use IME, the associated activity
- // behind the starting window may request the input. If so, then we should still hold
- // the IME parent change until the activity started the input.
- boolean imeLayeringTargetMayUseIme =
- LayoutParams.mayUseInputMethod(mImeLayeringTarget.mAttrs.flags)
- || mImeLayeringTarget.mAttrs.type == TYPE_APPLICATION_STARTING;
- if (imeLayeringTargetMayUseIme && (mImeInputTarget == null
- || mImeLayeringTarget.mActivityRecord != mImeInputTarget.getActivityRecord())) {
- // Do not change parent if the window hasn't requested IME.
- return null;
- }
+ if (!canComputeImeParent(mImeLayeringTarget, mImeInputTarget)) {
+ return null;
}
// Attach it to app if the target is part of an app and such app is covering the entire
// screen. If it's not covering the entire screen the IME might extend beyond the apps
@@ -4535,6 +4519,76 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
? mImeWindowsContainer.getParent().getSurfaceControl() : null;
}
+ private static boolean canComputeImeParent(@Nullable WindowState imeLayeringTarget,
+ @Nullable InputTarget imeInputTarget) {
+ if (imeLayeringTarget == null) {
+ return false;
+ }
+ if (shouldComputeImeParentForEmbeddedActivity(imeLayeringTarget, imeInputTarget)) {
+ return true;
+ }
+ // Ensure changing the IME parent when the layering target that may use IME has
+ // became to the input target for preventing IME flickers.
+ // Note that:
+ // 1) For the imeLayeringTarget that may not use IME but requires IME on top
+ // of it (e.g. an overlay window with NOT_FOCUSABLE|ALT_FOCUSABLE_IM flags), we allow
+ // it to re-parent the IME on top the display to keep the legacy behavior.
+ // 2) Even though the starting window won't use IME, the associated activity
+ // behind the starting window may request the input. If so, then we should still hold
+ // the IME parent change until the activity started the input.
+ boolean imeLayeringTargetMayUseIme =
+ LayoutParams.mayUseInputMethod(imeLayeringTarget.mAttrs.flags)
+ || imeLayeringTarget.mAttrs.type == TYPE_APPLICATION_STARTING;
+
+ if (imeLayeringTargetMayUseIme && (imeInputTarget == null
+ || imeLayeringTarget.mActivityRecord != imeInputTarget.getActivityRecord())) {
+ // Do not change parent if the window hasn't requested IME.
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Called from {@link #computeImeParent()} to check the given IME targets if the IME surface
+ * parent should be updated in ActivityEmbeddings.
+ *
+ * As the IME layering target is calculated according to the window hierarchy by
+ * {@link #computeImeTarget}, the layering target and input target may be different when the
+ * window hasn't started input connection, WindowManagerService hasn't yet received the
+ * input target which reported from InputMethodManagerService. To make the IME surface will be
+ * shown on the best fit IME layering target, we basically won't update IME parent until both
+ * IME input and layering target updated for better IME transition.
+ *
+ * However, in activity embedding, tapping a window won't update it to the top window so the
+ * calculated IME layering target may higher than input target. Update IME parent for this case.
+ *
+ * @return {@code true} means the layer of IME layering target is higher than the input target
+ * and {@link #computeImeParent()} should keep progressing to update the IME
+ * surface parent on the display in case the IME surface left behind.
+ */
+ private static boolean shouldComputeImeParentForEmbeddedActivity(
+ @Nullable WindowState imeLayeringTarget, @Nullable InputTarget imeInputTarget) {
+ if (imeInputTarget == null || imeLayeringTarget == null) {
+ return false;
+ }
+ final WindowState inputTargetWindow = imeInputTarget.getWindowState();
+ if (inputTargetWindow == null || !imeLayeringTarget.isAttached()
+ || !inputTargetWindow.isAttached()) {
+ return false;
+ }
+
+ final ActivityRecord inputTargetRecord = imeInputTarget.getActivityRecord();
+ final ActivityRecord layeringTargetRecord = imeLayeringTarget.getActivityRecord();
+ if (inputTargetRecord == null || layeringTargetRecord == null
+ || inputTargetRecord == layeringTargetRecord
+ || inputTargetRecord.getTask() != layeringTargetRecord.getTask()
+ || !inputTargetRecord.isEmbedded() || !layeringTargetRecord.isEmbedded()) {
+ // Check whether the input target and layering target are embedded in the same Task.
+ return false;
+ }
+ return imeLayeringTarget.compareTo(inputTargetWindow) > 0;
+ }
+
void setLayoutNeeded() {
if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
mLayoutNeeded = true;
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 8e9a21490645..41130812d658 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1577,9 +1577,8 @@ public class DisplayPolicy {
applyKeyguardPolicy(win, imeTarget);
// Check if the freeform window overlaps with the navigation bar area.
- final boolean isOverlappingWithNavBar = isOverlappingWithNavBar(win);
- if (isOverlappingWithNavBar && !mIsFreeformWindowOverlappingWithNavBar
- && win.inFreeformWindowingMode()) {
+ if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode()
+ && win.mActivityRecord != null && isOverlappingWithNavBar(win)) {
mIsFreeformWindowOverlappingWithNavBar = true;
}
@@ -1637,7 +1636,7 @@ public class DisplayPolicy {
// mode; if it's in gesture navigation mode, the navigation bar will be
// NAV_BAR_FORCE_TRANSPARENT and its appearance won't be decided by overlapping
// windows.
- if (isOverlappingWithNavBar) {
+ if (isOverlappingWithNavBar(win)) {
if (mNavBarColorWindowCandidate == null) {
mNavBarColorWindowCandidate = win;
addSystemBarColorApp(win);
@@ -1665,7 +1664,7 @@ public class DisplayPolicy {
addSystemBarColorApp(win);
}
}
- if (isOverlappingWithNavBar && mNavBarColorWindowCandidate == null) {
+ if (isOverlappingWithNavBar(win) && mNavBarColorWindowCandidate == null) {
mNavBarColorWindowCandidate = win;
}
}
@@ -2858,7 +2857,7 @@ public class DisplayPolicy {
@VisibleForTesting
static boolean isOverlappingWithNavBar(@NonNull WindowState win) {
- if (win.mActivityRecord == null || !win.isVisible()) {
+ if (!win.isVisible()) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
index 47bdba34ee24..41eb2c92923f 100644
--- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
@@ -359,12 +359,6 @@ final class DisplayRotationCompatPolicy {
CAMERA_OPENED_ROTATION_UPDATE_DELAY_MS);
}
- private void updateOrientationWithWmLock() {
- synchronized (mWmService.mGlobalLock) {
- mDisplayContent.updateOrientation();
- }
- }
-
private void delayedUpdateOrientationWithWmLock(
@NonNull String cameraId, @NonNull String packageName) {
synchronized (this) {
@@ -375,25 +369,28 @@ final class DisplayRotationCompatPolicy {
}
mCameraIdPackageBiMap.put(packageName, cameraId);
}
- ActivityRecord topActivity = mDisplayContent.topRunningActivity(
- /* considerKeyguardState= */ true);
- if (topActivity == null || topActivity.getTask() == null) {
- return;
- }
- // Checking whether an activity in fullscreen rather than the task as this camera compat
- // treatment doesn't cover activity embedding.
- if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
- if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
- topActivity.recomputeConfiguration();
+ synchronized (mWmService.mGlobalLock) {
+ ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+ /* considerKeyguardState= */ true);
+ if (topActivity == null || topActivity.getTask() == null) {
+ return;
+ }
+ // Checking whether an activity in fullscreen rather than the task as this camera
+ // compat treatment doesn't cover activity embedding.
+ if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ if (topActivity.mLetterboxUiController
+ .isOverrideOrientationOnlyForCameraEnabled()) {
+ topActivity.recomputeConfiguration();
+ }
+ mDisplayContent.updateOrientation();
+ return;
+ }
+ // Checking that the whole app is in multi-window mode as we shouldn't show toast
+ // for the activity embedding case.
+ if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
+ && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) {
+ showToast(R.string.display_rotation_camera_compat_toast_in_split_screen);
}
- updateOrientationWithWmLock();
- return;
- }
- // Checking that the whole app is in multi-window mode as we shouldn't show toast
- // for the activity embedding case.
- if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
- && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) {
- showToast(R.string.display_rotation_camera_compat_toast_in_split_screen);
}
}
@@ -441,18 +438,20 @@ final class DisplayRotationCompatPolicy {
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Display id=%d is notified that Camera %s is closed, updating rotation.",
mDisplayContent.mDisplayId, cameraId);
- ActivityRecord topActivity = mDisplayContent.topRunningActivity(
- /* considerKeyguardState= */ true);
- if (topActivity == null
- // Checking whether an activity in fullscreen rather than the task as this camera
- // compat treatment doesn't cover activity embedding.
- || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
- return;
- }
- if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
- topActivity.recomputeConfiguration();
+ synchronized (mWmService.mGlobalLock) {
+ ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+ /* considerKeyguardState= */ true);
+ if (topActivity == null
+ // Checking whether an activity in fullscreen rather than the task as this
+ // camera compat treatment doesn't cover activity embedding.
+ || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+ return;
+ }
+ if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
+ topActivity.recomputeConfiguration();
+ }
+ mDisplayContent.updateOrientation();
}
- updateOrientationWithWmLock();
}
private boolean isActivityForCameraIdRefreshing(String cameraId) {
diff --git a/services/core/java/com/android/server/wm/EventLogTags.logtags b/services/core/java/com/android/server/wm/EventLogTags.logtags
index 1e5a219e5e52..385d9142b807 100644
--- a/services/core/java/com/android/server/wm/EventLogTags.logtags
+++ b/services/core/java/com/android/server/wm/EventLogTags.logtags
@@ -1,4 +1,4 @@
-# See system/core/logcat/event.logtags for a description of the format of this file.
+# See system/logging/logcat/event.logtags for a description of the format of this file.
option java_package com.android.server.wm
@@ -52,7 +52,7 @@ option java_package com.android.server.wm
30066 wm_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3)
# Keyguard status changed
-30067 wm_set_keyguard_shown (Display Id|1|5),(keyguardShowing|1),(aodShowing|1),(keyguardGoingAway|1),(Reason|3)
+30067 wm_set_keyguard_shown (Display Id|1|5),(keyguardShowing|1),(aodShowing|1),(keyguardGoingAway|1),(occluded|1),(Reason|3)
# Out of memory for surfaces.
31000 wm_no_surface_memory (Window|3),(PID|1|5),(Operation|3)
@@ -62,8 +62,14 @@ option java_package com.android.server.wm
31002 wm_task_moved (TaskId|1|5),(ToTop|1),(Index|1)
# Task removed with source explanation.
31003 wm_task_removed (TaskId|1|5),(Reason|3)
+
+# Set the requested orientation of an activity.
+31006 wm_set_requested_orientation (Orientation|1|5),(Component Name|3)
+
# bootanim finished:
31007 wm_boot_animation_done (time|2|3)
+# Notify keyguard occlude statuc change to SysUI.
+31008 wm_set_keyguard_occluded (occluded|1),(animate|1),(transit|1),(Channel|3)
# Request surface flinger to show / hide the wallpaper surface.
33001 wm_wallpaper_surface (Display Id|1|5),(Visible|1),(Target|3)
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 1d21b9d8c141..574ab83eed0c 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -188,6 +188,7 @@ class KeyguardController {
keyguardShowing ? 1 : 0,
aodShowing ? 1 : 0,
state.mKeyguardGoingAway ? 1 : 0,
+ state.mOccluded ? 1 : 0,
"setKeyguardShown");
// Update the task snapshot if the screen will not be turned off. To make sure that the
@@ -255,9 +256,10 @@ class KeyguardController {
try {
EventLogTags.writeWmSetKeyguardShown(
displayId,
- 1 /* keyguardShowing */,
+ state.mKeyguardShowing ? 1 : 0,
state.mAodShowing ? 1 : 0,
1 /* keyguardGoingAway */,
+ state.mOccluded ? 1 : 0,
"keyguardGoingAway");
final int transitFlags = convertTransitFlags(flags);
final DisplayContent dc = mRootWindowContainer.getDefaultDisplay();
@@ -671,6 +673,15 @@ class KeyguardController {
boolean hasChange = false;
if (lastOccluded != mOccluded) {
+ if (mDisplayId == DEFAULT_DISPLAY) {
+ EventLogTags.writeWmSetKeyguardShown(
+ mDisplayId,
+ mKeyguardShowing ? 1 : 0,
+ mAodShowing ? 1 : 0,
+ mKeyguardGoingAway ? 1 : 0,
+ mOccluded ? 1 : 0,
+ "updateVisibility");
+ }
controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity);
hasChange = true;
} else if (!lastKeyguardGoingAway && mKeyguardGoingAway) {
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 513667024caa..37cf5bc95a23 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -19,9 +19,11 @@ package com.android.server.wm;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ALLOW_IGNORE_ORIENTATION_REQUEST;
+import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_CAMERA_COMPAT_TREATMENT;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_COMPAT_FAKE_FOCUS;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY;
+import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -296,7 +298,6 @@ final class LetterboxConfiguration {
R.bool.config_isCompatFakeFocusEnabled);
mIsPolicyForIgnoringRequestedOrientationEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled);
-
mIsDisplayRotationImmersiveAppCompatPolicyEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled);
mDeviceConfig.updateFlagActiveStatus(
@@ -311,6 +312,12 @@ final class LetterboxConfiguration {
mDeviceConfig.updateFlagActiveStatus(
/* isActive */ mIsCompatFakeFocusEnabled,
/* key */ KEY_ENABLE_COMPAT_FAKE_FOCUS);
+ mDeviceConfig.updateFlagActiveStatus(
+ /* isActive */ mTranslucentLetterboxingEnabled,
+ /* key */ KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY);
+ mDeviceConfig.updateFlagActiveStatus(
+ /* isActive */ true,
+ /* key */ KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP);
mLetterboxConfigurationPersister = letterboxConfigurationPersister;
mLetterboxConfigurationPersister.start();
@@ -325,6 +332,16 @@ final class LetterboxConfiguration {
}
/**
+ * Whether size compat mode is disabled after an orientation change request comes from the app.
+ * This value is controlled via {@link android.provider.DeviceConfig}.
+ */
+ // TODO(b/270356567) Clean up this flag
+ boolean isSizeCompatModeDisabledAfterOrientationChangeFromApp() {
+ return mDeviceConfig.getFlag(
+ KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP);
+ }
+
+ /**
* Overrides the aspect ratio of letterbox for fixed orientation. If given value is <= {@link
* #MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO}, both it and a value of {@link
* com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio} will be ignored and
@@ -1003,7 +1020,7 @@ final class LetterboxConfiguration {
boolean isTranslucentLetterboxingEnabled() {
return mTranslucentLetterboxingOverrideEnabled || (mTranslucentLetterboxingEnabled
- && isTranslucentLetterboxingAllowed());
+ && mDeviceConfig.getFlag(KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY));
}
void setTranslucentLetterboxingEnabled(boolean translucentLetterboxingEnabled) {
@@ -1051,13 +1068,6 @@ final class LetterboxConfiguration {
isDeviceInTabletopMode, nextVerticalPosition);
}
- // TODO(b/262378106): Cache a runtime flag and implement
- // DeviceConfig.OnPropertiesChangedListener
- static boolean isTranslucentLetterboxingAllowed() {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- "enable_translucent_activity_letterbox", false);
- }
-
/** Whether fake sending focus is enabled for unfocused apps in splitscreen */
boolean isCompatFakeFocusEnabled() {
return mIsCompatFakeFocusEnabled && mDeviceConfig.getFlag(KEY_ENABLE_COMPAT_FAKE_FOCUS);
diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
index b364872e56e7..1651af328b1f 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.provider.DeviceConfig;
import android.util.ArraySet;
-
import com.android.internal.annotations.VisibleForTesting;
import java.util.Map;
@@ -48,6 +47,16 @@ final class LetterboxConfigurationDeviceConfig
static final String KEY_ENABLE_COMPAT_FAKE_FOCUS = "enable_compat_fake_focus";
private static final boolean DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS = true;
+ static final String KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY =
+ "enable_letterbox_translucent_activity";
+
+ private static final boolean DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY = true;
+
+ static final String KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP =
+ "disable_size_compat_mode_after_orientation_change_from_app";
+ private static final boolean
+ DEFAULT_VALUE_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP = true;
+
@VisibleForTesting
static final Map<String, Boolean> sKeyToDefaultValueMap = Map.of(
KEY_ENABLE_CAMERA_COMPAT_TREATMENT,
@@ -57,7 +66,11 @@ final class LetterboxConfigurationDeviceConfig
KEY_ALLOW_IGNORE_ORIENTATION_REQUEST,
DEFAULT_VALUE_ALLOW_IGNORE_ORIENTATION_REQUEST,
KEY_ENABLE_COMPAT_FAKE_FOCUS,
- DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS
+ DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS,
+ KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY,
+ DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY,
+ KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP,
+ DEFAULT_VALUE_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP
);
// Whether camera compatibility treatment is enabled.
@@ -82,6 +95,14 @@ final class LetterboxConfigurationDeviceConfig
// which isn't guaranteed by default in multi-window modes.
private boolean mIsCompatFakeFocusAllowed = DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS;
+ // Whether the letterbox strategy for transparent activities is allowed
+ private boolean mIsTranslucentLetterboxingAllowed =
+ DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY;
+
+ // Whether size compat mode is disabled after an orientation change request comes from the app
+ private boolean mIsSizeCompatModeDisabledAfterOrientationChangeFromApp =
+ DEFAULT_VALUE_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP;
+
// Set of active device configs that need to be updated in
// DeviceConfig.OnPropertiesChangedListener#onPropertiesChanged.
private final ArraySet<String> mActiveDeviceConfigsSet = new ArraySet<>();
@@ -129,6 +150,10 @@ final class LetterboxConfigurationDeviceConfig
return mIsAllowIgnoreOrientationRequest;
case KEY_ENABLE_COMPAT_FAKE_FOCUS:
return mIsCompatFakeFocusAllowed;
+ case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY:
+ return mIsTranslucentLetterboxingAllowed;
+ case KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP:
+ return mIsSizeCompatModeDisabledAfterOrientationChangeFromApp;
default:
throw new AssertionError("Unexpected flag name: " + key);
}
@@ -141,19 +166,23 @@ final class LetterboxConfigurationDeviceConfig
}
switch (key) {
case KEY_ENABLE_CAMERA_COMPAT_TREATMENT:
- mIsCameraCompatTreatmentEnabled =
- getDeviceConfig(key, defaultValue);
+ mIsCameraCompatTreatmentEnabled = getDeviceConfig(key, defaultValue);
break;
case KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY:
mIsDisplayRotationImmersiveAppCompatPolicyEnabled =
getDeviceConfig(key, defaultValue);
break;
case KEY_ALLOW_IGNORE_ORIENTATION_REQUEST:
- mIsAllowIgnoreOrientationRequest =
- getDeviceConfig(key, defaultValue);
+ mIsAllowIgnoreOrientationRequest = getDeviceConfig(key, defaultValue);
break;
case KEY_ENABLE_COMPAT_FAKE_FOCUS:
- mIsCompatFakeFocusAllowed =
+ mIsCompatFakeFocusAllowed = getDeviceConfig(key, defaultValue);
+ break;
+ case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY:
+ mIsTranslucentLetterboxingAllowed = getDeviceConfig(key, defaultValue);
+ break;
+ case KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP:
+ mIsSizeCompatModeDisabledAfterOrientationChangeFromApp =
getDeviceConfig(key, defaultValue);
break;
default:
diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java b/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java
index 4a99db594755..3b10debaa753 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java
@@ -216,6 +216,10 @@ class LetterboxConfigurationPersister {
}
private void readCurrentConfiguration() {
+ if (!mConfigurationFile.exists()) {
+ useDefaultValue();
+ return;
+ }
FileInputStream fis = null;
try {
fis = mConfigurationFile.openRead();
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index e3437683e957..d9f2b6e4a0a3 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -193,12 +193,6 @@ final class LetterboxUiController {
// The app compat state for the opaque activity if any
private int mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
- // If true it means that the opaque activity beneath a translucent one is in SizeCompatMode.
- private boolean mIsInheritedInSizeCompatMode;
-
- // This is the SizeCompatScale of the opaque activity beneath a translucent one
- private float mInheritedSizeCompatScale;
-
// The CompatDisplayInsets of the opaque activity beneath the translucent one.
private ActivityRecord.CompatDisplayInsets mInheritedCompatDisplayInsets;
@@ -735,8 +729,21 @@ final class LetterboxUiController {
: mActivityRecord.inMultiWindowMode()
? mActivityRecord.getTask().getBounds()
: mActivityRecord.getRootTask().getParent().getBounds();
+ // In case of translucent activities an option is to use the WindowState#getFrame() of
+ // the first opaque activity beneath. In some cases (e.g. an opaque activity is using
+ // non MATCH_PARENT layouts or a Dialog theme) this might not provide the correct
+ // information and in particular it might provide a value for a smaller area making
+ // the letterbox overlap with the translucent activity's frame.
+ // If we use WindowState#getFrame() for the translucent activity's letterbox inner
+ // frame, the letterbox will then be overlapped with the translucent activity's frame.
+ // Because the surface layer of letterbox is lower than an activity window, this
+ // won't crop the content, but it may affect other features that rely on values stored
+ // in mLetterbox, e.g. transitions, a status bar scrim and recents preview in Launcher
+ // For this reason we use ActivityRecord#getBounds() that the translucent activity
+ // inherits from the first opaque activity beneath and also takes care of the scaling
+ // in case of activities in size compat mode.
final Rect innerFrame = hasInheritedLetterboxBehavior()
- ? mActivityRecord.getWindowConfiguration().getBounds() : w.getFrame();
+ ? mActivityRecord.getBounds() : w.getFrame();
mLetterbox.layout(spaceToFill, innerFrame, mTmpPoint);
} else if (mLetterbox != null) {
mLetterbox.hide();
@@ -863,10 +870,9 @@ final class LetterboxUiController {
return mActivityRecord.mWmService.mContext.getResources();
}
- private void handleHorizontalDoubleTap(int x) {
- // TODO(b/260857308): Investigate if enabling reachability for translucent activity
- if (hasInheritedLetterboxBehavior() || !isHorizontalReachabilityEnabled()
- || mActivityRecord.isInTransition()) {
+ @VisibleForTesting
+ void handleHorizontalDoubleTap(int x) {
+ if (!isHorizontalReachabilityEnabled() || mActivityRecord.isInTransition()) {
return;
}
@@ -904,10 +910,9 @@ final class LetterboxUiController {
mActivityRecord.recomputeConfiguration();
}
- private void handleVerticalDoubleTap(int y) {
- // TODO(b/260857308): Investigate if enabling reachability for translucent activity
- if (hasInheritedLetterboxBehavior() || !isVerticalReachabilityEnabled()
- || mActivityRecord.isInTransition()) {
+ @VisibleForTesting
+ void handleVerticalDoubleTap(int y) {
+ if (!isVerticalReachabilityEnabled() || mActivityRecord.isInTransition()) {
return;
}
@@ -1386,10 +1391,10 @@ final class LetterboxUiController {
mLetterboxConfigListener.onRemoved();
clearInheritedConfig();
}
- // In case mActivityRecord.getCompatDisplayInsets() is not null we don't apply the
+ // In case mActivityRecord.hasCompatDisplayInsetsWithoutOverride() we don't apply the
// opaque activity constraints because we're expecting the activity is already letterboxed.
- if (mActivityRecord.getTask() == null || mActivityRecord.getCompatDisplayInsets() != null
- || mActivityRecord.fillsParent()) {
+ if (mActivityRecord.getTask() == null || mActivityRecord.fillsParent()
+ || mActivityRecord.hasCompatDisplayInsetsWithoutInheritance()) {
return;
}
final ActivityRecord firstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity(
@@ -1417,6 +1422,7 @@ final class LetterboxUiController {
// We need to initialize appBounds to avoid NPE. The actual value will
// be set ahead when resolving the Configuration for the activity.
mutatedConfiguration.windowConfiguration.setAppBounds(new Rect());
+ inheritConfiguration(firstOpaqueActivityBeneath);
return mutatedConfiguration;
});
}
@@ -1427,7 +1433,7 @@ final class LetterboxUiController {
* the first opaque activity beneath.
*/
boolean hasInheritedLetterboxBehavior() {
- return mLetterboxConfigListener != null && !mActivityRecord.matchParentBounds();
+ return mLetterboxConfigListener != null;
}
/**
@@ -1457,16 +1463,12 @@ final class LetterboxUiController {
return mInheritedAppCompatState;
}
- float getInheritedSizeCompatScale() {
- return mInheritedSizeCompatScale;
- }
-
@Configuration.Orientation
int getInheritedOrientation() {
return mInheritedOrientation;
}
- public ActivityRecord.CompatDisplayInsets getInheritedCompatDisplayInsets() {
+ ActivityRecord.CompatDisplayInsets getInheritedCompatDisplayInsets() {
return mInheritedCompatDisplayInsets;
}
@@ -1486,7 +1488,7 @@ final class LetterboxUiController {
* @return The first not finishing opaque activity beneath the current translucent activity
* if it exists and the strategy is enabled.
*/
- private Optional<ActivityRecord> findOpaqueNotFinishingActivityBelow() {
+ Optional<ActivityRecord> findOpaqueNotFinishingActivityBelow() {
if (!hasInheritedLetterboxBehavior() || mActivityRecord.getTask() == null) {
return Optional.empty();
}
@@ -1508,8 +1510,6 @@ final class LetterboxUiController {
}
mInheritedOrientation = firstOpaque.getRequestedConfigurationOrientation();
mInheritedAppCompatState = firstOpaque.getAppCompatState();
- mIsInheritedInSizeCompatMode = firstOpaque.inSizeCompatMode();
- mInheritedSizeCompatScale = firstOpaque.getCompatScale();
mInheritedCompatDisplayInsets = firstOpaque.getCompatDisplayInsets();
}
@@ -1519,8 +1519,6 @@ final class LetterboxUiController {
mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO;
mInheritedOrientation = Configuration.ORIENTATION_UNDEFINED;
mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
- mIsInheritedInSizeCompatMode = false;
- mInheritedSizeCompatScale = 1f;
mInheritedCompatDisplayInsets = null;
}
}
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 4c5d607ef7be..0239b989d3c2 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
+
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
@@ -194,6 +196,13 @@ class RemoteAnimationController implements DeathRecipient {
+ " transit=%s, apps=%d, wallpapers=%d, nonApps=%d",
AppTransition.appTransitionOldToString(transit), appTargets.length,
wallpaperTargets.length, nonAppTargets.length);
+ if (AppTransition.isKeyguardOccludeTransitOld(transit)) {
+ EventLogTags.writeWmSetKeyguardOccluded(
+ transit == TRANSIT_OLD_KEYGUARD_UNOCCLUDE ? 0 : 1,
+ 1 /* animate */,
+ transit,
+ "onAnimationStart");
+ }
mRemoteAnimationAdapter.getRunner().onAnimationStart(transit, appTargets,
wallpaperTargets, nonAppTargets, mFinishedCallback);
} catch (RemoteException e) {
@@ -353,6 +362,11 @@ class RemoteAnimationController implements DeathRecipient {
final boolean isKeyguardOccluded = mDisplayContent.isKeyguardOccluded();
try {
+ EventLogTags.writeWmSetKeyguardOccluded(
+ isKeyguardOccluded ? 1 : 0,
+ 0 /* animate */,
+ 0 /* transit */,
+ "onAnimationCancelled");
mRemoteAnimationAdapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to notify cancel", e);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3aa80c4ccefb..ddfd5ae2f27d 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3455,6 +3455,11 @@ class Task extends TaskFragment {
&& top.getOrganizedTask() == this && top.isState(RESUMED);
// Whether the direct top activity is in size compat mode on foreground.
info.topActivityInSizeCompat = isTopActivityResumed && top.inSizeCompatMode();
+ if (info.topActivityInSizeCompat
+ && mWmService.mLetterboxConfiguration.isTranslucentLetterboxingEnabled()) {
+ // We hide the restart button in case of transparent activities.
+ info.topActivityInSizeCompat = top.fillsParent();
+ }
// Whether the direct top activity is eligible for letterbox education.
info.topActivityEligibleForLetterboxEducation = isTopActivityResumed
&& top.isEligibleForLetterboxEducation();
@@ -5879,8 +5884,11 @@ class Task extends TaskFragment {
final int taskId = activity != null
? mTaskSupervisor.getNextTaskIdForUser(activity.mUserId)
: mTaskSupervisor.getNextTaskIdForUser();
+ final int activityType = getActivityType();
task = new Task.Builder(mAtmService)
.setTaskId(taskId)
+ .setActivityType(activityType != ACTIVITY_TYPE_UNDEFINED ? activityType
+ : ACTIVITY_TYPE_STANDARD)
.setActivityInfo(info)
.setActivityOptions(options)
.setIntent(intent)
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 79be9463aa05..2086b522aa66 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -1222,7 +1222,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
// Clear last paused activity if focused root task changed while sleeping, so that the
// top activity of current focused task can be resumed.
- if (mDisplayContent.isSleeping()) {
+ if (mDisplayContent.isSleeping() && currentFocusedTask != null) {
currentFocusedTask.clearLastPausedActivity();
}
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 22da56ad4d3b..19e45ff02463 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1953,7 +1953,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
1f);
mBackScreenshots.put(r.mActivityComponent.flattenToString(), backBuffer);
}
- child.asActivityRecord().inHistory = true;
+ addingActivity.inHistory = true;
task.onDescendantActivityAdded(taskHadActivity, activityType, addingActivity);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index ce032442e4af..7ff92afc9d29 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1436,7 +1436,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
* {@link Configuration#ORIENTATION_PORTRAIT},
* {@link Configuration#ORIENTATION_UNDEFINED}).
*/
- @ScreenOrientation
+ @Configuration.Orientation
int getRequestedConfigurationOrientation() {
return getRequestedConfigurationOrientation(false /* forDisplay */);
}
@@ -1454,9 +1454,28 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
* {@link Configuration#ORIENTATION_PORTRAIT},
* {@link Configuration#ORIENTATION_UNDEFINED}).
*/
- @ScreenOrientation
+ @Configuration.Orientation
int getRequestedConfigurationOrientation(boolean forDisplay) {
- int requestedOrientation = getOverrideOrientation();
+ return getRequestedConfigurationOrientation(forDisplay, getOverrideOrientation());
+ }
+
+ /**
+ * Gets the configuration orientation by the requested screen orientation
+ *
+ * @param forDisplay whether it is the requested config orientation for display.
+ * If {@code true}, we may reverse the requested orientation if the root is
+ * different from the display, so that when the display rotates to the
+ * reversed orientation, the requested app will be in the requested
+ * orientation.
+ * @param requestedOrientation the screen orientation({@link ScreenOrientation}) that is
+ * requested
+ * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
+ * {@link Configuration#ORIENTATION_PORTRAIT},
+ * {@link Configuration#ORIENTATION_UNDEFINED}).
+ */
+ @Configuration.Orientation
+ int getRequestedConfigurationOrientation(boolean forDisplay,
+ @ScreenOrientation int requestedOrientation) {
final RootDisplayArea root = getRootDisplayArea();
if (forDisplay && root != null && root.isOrientationDifferentFromDisplay()) {
// Reverse the requested orientation if the orientation of its root is different from
@@ -1466,7 +1485,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
// (portrait).
// When an app below the DAG is requesting landscape, it should actually request the
// display to be portrait, so that the DAG and the app will be in landscape.
- requestedOrientation = reverseOrientation(getOverrideOrientation());
+ requestedOrientation = reverseOrientation(requestedOrientation);
}
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8931d8030df2..e6c1e75da581 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6198,9 +6198,10 @@ public class WindowManagerService extends IWindowManager.Stub
waitingForConfig = waitingForRemoteDisplayChange = false;
numOpeningApps = 0;
}
- if (waitingForConfig || waitingForRemoteDisplayChange || mAppsFreezingScreen > 0
- || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE
- || mClientFreezingScreen || numOpeningApps > 0) {
+ final boolean waitingForApps = mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT
+ && (mAppsFreezingScreen > 0 || numOpeningApps > 0);
+ if (waitingForConfig || waitingForRemoteDisplayChange || waitingForApps
+ || mClientFreezingScreen) {
ProtoLog.d(WM_DEBUG_ORIENTATION, "stopFreezingDisplayLocked: Returning "
+ "waitingForConfig=%b, waitingForRemoteDisplayChange=%b, "
+ "mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, "
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 52f2b6351265..41e0fd715889 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4577,7 +4577,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void requestUpdateWallpaperIfNeeded() {
final DisplayContent dc = getDisplayContent();
- if (dc != null && hasWallpaper()) {
+ if (dc != null && ((mIsWallpaper && !mLastConfigReportedToClient) || hasWallpaper())) {
dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
dc.setLayoutNeeded();
mWmService.mWindowPlacerLocked.requestTraversal();
diff --git a/services/people/java/com/android/server/people/data/ContactsQueryHelper.java b/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
index 0993295e162f..2505abf2d160 100644
--- a/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
+++ b/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
@@ -152,6 +152,8 @@ class ContactsQueryHelper {
}
} catch (SQLiteException exception) {
Slog.w("SQLite exception when querying contacts.", exception);
+ } catch (IllegalArgumentException exception) {
+ Slog.w("Illegal Argument exception when querying contacts.", exception);
}
if (found && lookupKey != null && hasPhoneNumber) {
return queryPhoneNumber(lookupKey);
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index eff9e8da9a76..872734f7a01d 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -129,7 +129,6 @@ public class DataManager {
private final List<PeopleService.ConversationsListener> mConversationsListeners =
new ArrayList<>(1);
private final Handler mHandler;
-
private ContentObserver mCallLogContentObserver;
private ContentObserver mMmsSmsContentObserver;
@@ -1106,6 +1105,7 @@ public class DataManager {
@NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
mInjector.getBackgroundExecutor().execute(() -> {
PackageData packageData = getPackage(packageName, user.getIdentifier());
+ boolean hasCachedShortcut = false;
for (ShortcutInfo shortcut : shortcuts) {
if (ShortcutHelper.isConversationShortcut(
shortcut, mShortcutServiceInternal, user.getIdentifier())) {
@@ -1114,15 +1114,18 @@ public class DataManager {
? packageData.getConversationInfo(shortcut.getId()) : null;
if (conversationInfo == null
|| !conversationInfo.isShortcutCachedForNotification()) {
- // This is a newly cached shortcut. Clean up the existing cached
- // shortcuts to ensure the cache size is under the limit.
- cleanupCachedShortcuts(user.getIdentifier(),
- MAX_CACHED_RECENT_SHORTCUTS - 1);
+ hasCachedShortcut = true;
}
}
addOrUpdateConversationInfo(shortcut);
}
}
+ // Added at least one new conversation. Uncache older existing cached
+ // shortcuts to ensure the cache size is under the limit.
+ if (hasCachedShortcut) {
+ cleanupCachedShortcuts(user.getIdentifier(),
+ MAX_CACHED_RECENT_SHORTCUTS);
+ }
});
}
diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
index 35a677e0f816..817b245a78bf 100644
--- a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
@@ -377,6 +377,33 @@ public class PersistentDataStoreTest {
assertTrue(Float.isNaN(mDataStore.getBrightness(testDisplayDevice)));
}
+ @Test
+ public void testStoreAndRestoreBrightnessNitsForDefaultDisplay() {
+ float brightnessNitsForDefaultDisplay = 190;
+ mDataStore.loadIfNeeded();
+ mDataStore.setBrightnessNitsForDefaultDisplay(brightnessNitsForDefaultDisplay);
+
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ mInjector.setWriteStream(baos);
+ mDataStore.saveIfNeeded();
+ mTestLooper.dispatchAll();
+ assertTrue(mInjector.wasWriteSuccessful());
+ TestInjector newInjector = new TestInjector();
+ PersistentDataStore newDataStore = new PersistentDataStore(newInjector);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ newInjector.setReadStream(bais);
+ newDataStore.loadIfNeeded();
+ assertEquals(brightnessNitsForDefaultDisplay,
+ mDataStore.getBrightnessNitsForDefaultDisplay(), 0);
+ assertEquals(brightnessNitsForDefaultDisplay,
+ newDataStore.getBrightnessNitsForDefaultDisplay(), 0);
+ }
+
+ @Test
+ public void testInitialBrightnessNitsForDefaultDisplay() {
+ mDataStore.loadIfNeeded();
+ assertEquals(-1, mDataStore.getBrightnessNitsForDefaultDisplay(), 0);
+ }
public class TestInjector extends PersistentDataStore.Injector {
private InputStream mReadStream;
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 6c73f716493c..851d8f94d2c0 100644
--- a/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java
@@ -18,6 +18,8 @@ package com.android.server.dreams;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -39,10 +41,13 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.concurrent.Executor;
+
/**
* A collection of tests to exercise {@link DreamOverlayService}.
*/
@@ -60,6 +65,9 @@ public class DreamOverlayServiceTest {
@Mock
IDreamOverlayCallback mOverlayCallback;
+ @Mock
+ Executor mExecutor;
+
/**
* {@link TestDreamOverlayService} is a simple {@link DreamOverlayService} implementation for
* tracking interactions across {@link IDreamOverlay} binder interface. The service reports
@@ -78,8 +86,8 @@ public class DreamOverlayServiceTest {
private final Monitor mMonitor;
- TestDreamOverlayService(Monitor monitor) {
- super();
+ TestDreamOverlayService(Monitor monitor, Executor executor) {
+ super(executor);
mMonitor = monitor;
}
@@ -118,13 +126,63 @@ public class DreamOverlayServiceTest {
}
/**
+ * Verifies that callbacks for subclasses are run on the provided executor.
+ */
+ @Test
+ public void testCallbacksRunOnExecutor() throws RemoteException {
+ final TestDreamOverlayService.Monitor monitor = Mockito.mock(
+ TestDreamOverlayService.Monitor.class);
+ final TestDreamOverlayService service = new TestDreamOverlayService(monitor, mExecutor);
+ final IBinder binder = service.onBind(new Intent());
+ final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(binder);
+
+ final IDreamOverlayClient client = getClient(overlay);
+
+ // Start the dream.
+ client.startDream(mLayoutParams, mOverlayCallback,
+ FIRST_DREAM_COMPONENT.flattenToString(), false);
+
+ // The callback should not have run yet.
+ verify(monitor, never()).onStartDream();
+
+ // Run the Runnable sent to the executor.
+ ArgumentCaptor<Runnable> mRunnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+ verify(mExecutor).execute(mRunnableCaptor.capture());
+ mRunnableCaptor.getValue().run();
+
+ // Callback is run.
+ verify(monitor).onStartDream();
+
+ // Verify onWakeUp is run on the executor.
+ client.wakeUp();
+ verify(monitor, never()).onWakeUp();
+ mRunnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+ verify(mExecutor).execute(mRunnableCaptor.capture());
+ mRunnableCaptor.getValue().run();
+ verify(monitor).onWakeUp();
+
+ // Verify onEndDream is run on the executor.
+ client.endDream();
+ verify(monitor, never()).onEndDream();
+ mRunnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+ verify(mExecutor).execute(mRunnableCaptor.capture());
+ mRunnableCaptor.getValue().run();
+ verify(monitor).onEndDream();
+ }
+
+ /**
* Verifies that only the currently started dream is able to affect the overlay.
*/
@Test
public void testOverlayClientInteraction() throws RemoteException {
+ doAnswer(invocation -> {
+ ((Runnable) invocation.getArgument(0)).run();
+ return null;
+ }).when(mExecutor).execute(any());
+
final TestDreamOverlayService.Monitor monitor = Mockito.mock(
TestDreamOverlayService.Monitor.class);
- final TestDreamOverlayService service = new TestDreamOverlayService(monitor);
+ final TestDreamOverlayService service = new TestDreamOverlayService(monitor, mExecutor);
final IBinder binder = service.onBind(new Intent());
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(binder);
diff --git a/services/tests/servicestests/src/com/android/server/dreams/OWNERS b/services/tests/servicestests/src/com/android/server/dreams/OWNERS
new file mode 100644
index 000000000000..2f19cf557966
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/dreams/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/dreams/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/OWNERS b/services/tests/servicestests/src/com/android/server/media/projection/OWNERS
new file mode 100644
index 000000000000..832bcd9d70e6
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/media/projection/OWNERS
@@ -0,0 +1 @@
+include /media/java/android/media/projection/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java b/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
index 299f15344dfa..16a02b678511 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
@@ -91,8 +91,16 @@ public final class ContactsQueryHelperTest {
}
@Test
- public void testQueryException_returnsFalse() {
- contentProvider.setThrowException(true);
+ public void testQuerySQLiteException_returnsFalse() {
+ contentProvider.setThrowSQLiteException(true);
+
+ Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, CONTACT_LOOKUP_KEY);
+ assertFalse(mHelper.query(contactUri.toString()));
+ }
+
+ @Test
+ public void testQueryIllegalArgumentException_returnsFalse() {
+ contentProvider.setThrowIllegalArgumentException(true);
Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, CONTACT_LOOKUP_KEY);
assertFalse(mHelper.query(contactUri.toString()));
@@ -178,14 +186,18 @@ public final class ContactsQueryHelperTest {
private class ContactsContentProvider extends MockContentProvider {
private Map<Uri, Cursor> mUriPrefixToCursorMap = new ArrayMap<>();
- private boolean throwException = false;
+ private boolean mThrowSQLiteException = false;
+ private boolean mThrowIllegalArgumentException = false;
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
- if (throwException) {
+ if (mThrowSQLiteException) {
throw new SQLiteException();
}
+ if (mThrowIllegalArgumentException) {
+ throw new IllegalArgumentException();
+ }
for (Uri prefixUri : mUriPrefixToCursorMap.keySet()) {
if (uri.isPathPrefixMatch(prefixUri)) {
@@ -195,8 +207,12 @@ public final class ContactsQueryHelperTest {
return mUriPrefixToCursorMap.get(uri);
}
- public void setThrowException(boolean throwException) {
- this.throwException = throwException;
+ public void setThrowSQLiteException(boolean throwException) {
+ this.mThrowSQLiteException = throwException;
+ }
+
+ public void setThrowIllegalArgumentException(boolean throwException) {
+ this.mThrowIllegalArgumentException = throwException;
}
private void registerCursor(Uri uriPrefix, Cursor cursor) {
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 96e2a0916bb1..99a361c03a2a 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -18,6 +18,8 @@ package com.android.server.notification;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
+import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.NOT_FOREGROUND_SERVICE;
+import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.SHOW_IMMEDIATELY;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.Notification.FLAG_AUTO_CANCEL;
import static android.app.Notification.FLAG_BUBBLE;
@@ -1160,6 +1162,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
throws Exception {
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
NotificationChannel channel = new NotificationChannel("blocked", "name",
NotificationManager.IMPORTANCE_NONE);
@@ -1182,6 +1186,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
throws Exception {
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
NotificationChannel channel =
new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
@@ -1261,6 +1267,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -1590,6 +1598,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
+ mContext.getTestablePermissions().setPermission(
+ android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_GRANTED);
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED,
@@ -1618,6 +1630,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testEnqueueNotificationWithTag_FGSaddsFlags_dismissalNotAllowed() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
+ mContext.getTestablePermissions().setPermission(
+ android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_GRANTED);
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED,
@@ -1904,6 +1920,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
mBinderService.enqueueNotificationWithTag(PKG, PKG,
@@ -1918,7 +1936,27 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testCancelAllNotifications_FgsFlag_NoFgs_Allowed() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(NOT_FOREGROUND_SERVICE);
+ final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
+ sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
+ mBinderService.enqueueNotificationWithTag(PKG, PKG,
+ "testCancelAllNotifications_IgnoreForegroundService",
+ sbn.getId(), sbn.getNotification(), sbn.getUserId());
+ mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
+ waitForIdle();
+ StatusBarNotification[] notifs =
+ mBinderService.getActiveNotifications(sbn.getPackageName());
+ assertEquals(0, notifs.length);
+ }
+
+ @Test
public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
mBinderService.enqueueNotificationWithTag(PKG, PKG,
@@ -2006,6 +2044,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
Notification n =
new Notification.Builder(mContext, mTestNotificationChannel.getId())
.setSmallIcon(android.R.drawable.sym_def_app_icon)
@@ -2043,6 +2084,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationWithTag_fromApp_cannotCancelFgsChild()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
mService.isSystemUid = false;
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
@@ -2066,6 +2110,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationWithTag_fromApp_cannotCancelFgsParent()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
mService.isSystemUid = false;
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
@@ -2135,6 +2182,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelAllNotificationsFromApp_cannotCancelFgsChild()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
mService.isSystemUid = false;
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
@@ -2160,6 +2210,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelAllNotifications_fromApp_cannotCancelFgsParent()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
mService.isSystemUid = false;
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
@@ -2281,6 +2334,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_clearAll_GroupWithFgsParent()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -2304,6 +2360,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_clearAll_GroupWithFgsChild()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
final NotificationRecord child = generateNotificationRecord(
@@ -2402,6 +2461,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_clearAll_Fgs()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord child2 = generateNotificationRecord(
mTestNotificationChannel, 3, null, false);
child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -2466,6 +2528,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_byKey_GroupWithFgsParent()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -2491,6 +2556,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_byKey_GroupWithFgsChild()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
final NotificationRecord child = generateNotificationRecord(
@@ -2596,6 +2664,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_byKey_Fgs()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord child2 = generateNotificationRecord(
mTestNotificationChannel, 3, null, false);
child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -2762,6 +2833,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
final NotificationRecord child = generateNotificationRecord(
@@ -6199,6 +6273,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
Notification n = new Notification.Builder(mContext, "").build();
n.flags |= FLAG_FOREGROUND_SERVICE;
@@ -6218,6 +6295,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testRemoveForegroundServiceFlagFromNotification_posted() {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
Notification n = new Notification.Builder(mContext, "").build();
n.flags |= FLAG_FOREGROUND_SERVICE;
@@ -6240,6 +6320,68 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testCannotRemoveForegroundFlagWhenOverLimit_enqueued() {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
+ for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
+ Notification n = new Notification.Builder(mContext, "").build();
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
+ n, UserHandle.getUserHandleForUid(mUid), null, 0);
+ NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+ mService.addEnqueuedNotification(r);
+ }
+ Notification n = new Notification.Builder(mContext, "").build();
+ n.flags |= FLAG_FOREGROUND_SERVICE;
+
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG,
+ NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0,
+ n, UserHandle.getUserHandleForUid(mUid), null, 0);
+ NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+ mService.addEnqueuedNotification(r);
+
+ mInternalService.removeForegroundServiceFlagFromNotification(
+ PKG, r.getSbn().getId(), r.getSbn().getUserId());
+
+ waitForIdle();
+
+ assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS,
+ mService.getNotificationRecordCount());
+ }
+
+ @Test
+ public void testCannotRemoveForegroundFlagWhenOverLimit_posted() {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
+ for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
+ Notification n = new Notification.Builder(mContext, "").build();
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
+ n, UserHandle.getUserHandleForUid(mUid), null, 0);
+ NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+ mService.addNotification(r);
+ }
+ Notification n = new Notification.Builder(mContext, "").build();
+ n.flags |= FLAG_FOREGROUND_SERVICE;
+
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG,
+ NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0,
+ n, UserHandle.getUserHandleForUid(mUid), null, 0);
+ NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+ mService.addNotification(r);
+
+ mInternalService.removeForegroundServiceFlagFromNotification(
+ PKG, r.getSbn().getId(), r.getSbn().getUserId());
+
+ waitForIdle();
+
+ assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS,
+ mService.getNotificationRecordCount());
+ }
+
+ @Test
public void testAllowForegroundCustomToasts() throws Exception {
final String testPackage = "testPackageName";
assertEquals(0, mService.mToastQueue.size());
@@ -8230,7 +8372,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertNotNull(n.publicVersion.bigContentView);
assertNotNull(n.publicVersion.headsUpContentView);
- mService.fixNotification(n, PKG, "tag", 9, 0);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
assertNull(n.contentView);
assertNull(n.bigContentView);
@@ -8921,6 +9063,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCanPostFgsWhenOverLimit() throws RemoteException {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
i, null, false).getSbn();
@@ -8946,6 +9091,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCannotPostNonFgsWhenOverLimit() throws RemoteException {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
i, null, false).getSbn();
@@ -8968,6 +9116,17 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
"testCanPostFgsWhenOverLimit - non fgs over limit!",
sbn2.getId(), sbn2.getNotification(), sbn2.getUserId());
+
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(NOT_FOREGROUND_SERVICE);
+ final StatusBarNotification sbn3 = generateNotificationRecord(mTestNotificationChannel,
+ 101, null, false).getSbn();
+ sbn3.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
+ mBinderService.enqueueNotificationWithTag(PKG, PKG,
+ "testCanPostFgsWhenOverLimit - fake fgs over limit!",
+ sbn3.getId(), sbn3.getNotification(), sbn3.getUserId());
+
waitForIdle();
StatusBarNotification[] notifs =
@@ -10025,4 +10184,21 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mInternalService.sendReviewPermissionsNotification();
verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
}
+
+ @Test
+ public void fixNotification_withFgsFlag_butIsNotFgs() throws Exception {
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+ .thenReturn(applicationInfo);
+
+ Notification n = new Notification.Builder(mContext, "test")
+ .setFlag(FLAG_FOREGROUND_SERVICE, true)
+ .setFlag(FLAG_CAN_COLORIZE, true)
+ .build();
+
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
+
+ assertFalse(n.isForegroundService());
+ assertFalse(n.hasColorizedPermission());
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
index 949455a18570..b2754d237f42 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -32,22 +32,24 @@ import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.EventInfo;
import android.service.notification.ZenPolicy;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.UiServiceTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParserException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -189,8 +191,6 @@ public class ZenModeConfigTest extends UiServiceTestCase {
@Test
public void testRuleXml() throws Exception {
- String tag = "tag";
-
ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
rule.configurationActivity = new ComponentName("a", "a");
rule.component = new ComponentName("b", "b");
@@ -205,20 +205,11 @@ public class ZenModeConfigTest extends UiServiceTestCase {
rule.snoozing = true;
rule.pkg = "b";
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeRuleXml(rule, out);
- out.endTag(null, tag);
- out.endDocument();
+ writeRuleXml(rule, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig.ZenRule fromXml = readRuleXml(bais);
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
assertEquals("b", fromXml.pkg);
// always resets on reboot
assertFalse(fromXml.snoozing);
@@ -237,75 +228,41 @@ public class ZenModeConfigTest extends UiServiceTestCase {
@Test
public void testRuleXml_pkg_component() throws Exception {
- String tag = "tag";
-
ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
rule.configurationActivity = new ComponentName("a", "a");
rule.component = new ComponentName("b", "b");
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeRuleXml(rule, out);
- out.endTag(null, tag);
- out.endDocument();
+ writeRuleXml(rule, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig.ZenRule fromXml = readRuleXml(bais);
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
assertEquals("b", fromXml.pkg);
}
@Test
public void testRuleXml_pkg_configActivity() throws Exception {
- String tag = "tag";
-
ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
rule.configurationActivity = new ComponentName("a", "a");
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeRuleXml(rule, out);
- out.endTag(null, tag);
- out.endDocument();
+ writeRuleXml(rule, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig.ZenRule fromXml = readRuleXml(bais);
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
assertNull(fromXml.pkg);
}
@Test
public void testRuleXml_getPkg_nullPkg() throws Exception {
- String tag = "tag";
-
ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
rule.enabled = true;
rule.configurationActivity = new ComponentName("a", "a");
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeRuleXml(rule, out);
- out.endTag(null, tag);
- out.endDocument();
-
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
+ writeRuleXml(rule, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig.ZenRule fromXml = readRuleXml(bais);
assertEquals("a", fromXml.getPkg());
fromXml.condition = new Condition(Uri.EMPTY, "", Condition.STATE_TRUE);
@@ -313,25 +270,26 @@ public class ZenModeConfigTest extends UiServiceTestCase {
}
@Test
- public void testZenPolicyXml_allUnset() throws Exception {
- String tag = "tag";
+ public void testRuleXml_emptyConditionId() throws Exception {
+ ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+ rule.conditionId = Uri.EMPTY;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ writeRuleXml(rule, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig.ZenRule fromXml = readRuleXml(bais);
+
+ assertEquals(rule.condition, fromXml.condition);
+ }
+
+ @Test
+ public void testZenPolicyXml_allUnset() throws Exception {
ZenPolicy policy = new ZenPolicy.Builder().build();
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeZenPolicyXml(policy, out);
- out.endTag(null, tag);
- out.endDocument();
-
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenPolicy fromXml = ZenModeConfig.readZenPolicyXml(parser);
+ writePolicyXml(policy, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenPolicy fromXml = readPolicyXml(bais);
// nothing was set, so we should have nothing from the parser
assertNull(fromXml);
@@ -339,8 +297,6 @@ public class ZenModeConfigTest extends UiServiceTestCase {
@Test
public void testZenPolicyXml() throws Exception {
- String tag = "tag";
-
ZenPolicy policy = new ZenPolicy.Builder()
.allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
.allowMessages(ZenPolicy.PEOPLE_TYPE_NONE)
@@ -355,20 +311,10 @@ public class ZenModeConfigTest extends UiServiceTestCase {
.showVisualEffect(ZenPolicy.VISUAL_EFFECT_AMBIENT, true)
.build();
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeZenPolicyXml(policy, out);
- out.endTag(null, tag);
- out.endDocument();
-
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenPolicy fromXml = ZenModeConfig.readZenPolicyXml(parser);
+ writePolicyXml(policy, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenPolicy fromXml = readPolicyXml(bais);
assertNotNull(fromXml);
assertEquals(policy.getPriorityCategoryCalls(), fromXml.getPriorityCategoryCalls());
@@ -457,4 +403,45 @@ public class ZenModeConfigTest extends UiServiceTestCase {
config.suppressedVisualEffects = 0;
return config;
}
+
+ private void writeRuleXml(ZenModeConfig.ZenRule rule, ByteArrayOutputStream os)
+ throws IOException {
+ String tag = "tag";
+
+ TypedXmlSerializer out = Xml.newFastSerializer();
+ out.setOutput(new BufferedOutputStream(os), "utf-8");
+ out.startDocument(null, true);
+ out.startTag(null, tag);
+ ZenModeConfig.writeRuleXml(rule, out);
+ out.endTag(null, tag);
+ out.endDocument();
+ }
+
+ private ZenModeConfig.ZenRule readRuleXml(ByteArrayInputStream is)
+ throws XmlPullParserException, IOException {
+ TypedXmlPullParser parser = Xml.newFastPullParser();
+ parser.setInput(new BufferedInputStream(is), null);
+ parser.nextTag();
+ return ZenModeConfig.readRuleXml(parser);
+ }
+
+ private void writePolicyXml(ZenPolicy policy, ByteArrayOutputStream os) throws IOException {
+ String tag = "tag";
+
+ TypedXmlSerializer out = Xml.newFastSerializer();
+ out.setOutput(new BufferedOutputStream(os), "utf-8");
+ out.startDocument(null, true);
+ out.startTag(null, tag);
+ ZenModeConfig.writeZenPolicyXml(policy, out);
+ out.endTag(null, tag);
+ out.endDocument();
+ }
+
+ private ZenPolicy readPolicyXml(ByteArrayInputStream is)
+ throws XmlPullParserException, IOException {
+ TypedXmlPullParser parser = Xml.newFastPullParser();
+ parser.setInput(new BufferedInputStream(is), null);
+ parser.nextTag();
+ return ZenModeConfig.readZenPolicyXml(parser);
+ }
}
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 a017bd6a9436..0300eb06c220 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2324,6 +2324,32 @@ public class ActivityRecordTests extends WindowTestsBase {
}
@Test
+ public void testActivityServiceConnectionsHolder() {
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final ActivityServiceConnectionsHolder<Object> holder =
+ mAtm.mInternal.getServiceConnectionsHolder(activity.token);
+ assertNotNull(holder);
+ final Object connection = new Object();
+ holder.addConnection(connection);
+ assertTrue(holder.isActivityVisible());
+ final int[] count = new int[1];
+ final Consumer<Object> c = conn -> count[0]++;
+ holder.forEachConnection(c);
+ assertEquals(1, count[0]);
+
+ holder.removeConnection(connection);
+ holder.forEachConnection(c);
+ assertEquals(1, count[0]);
+
+ activity.setVisibleRequested(false);
+ activity.setState(STOPPED, "test");
+ assertFalse(holder.isActivityVisible());
+
+ activity.removeImmediately();
+ assertNull(mAtm.mInternal.getServiceConnectionsHolder(activity.token));
+ }
+
+ @Test
public void testTransferLaunchCookieWhenFinishing() {
final ActivityRecord activity1 = createActivityWithTask();
final Binder launchCookie = new Binder();
@@ -2351,7 +2377,7 @@ public class ActivityRecordTests extends WindowTestsBase {
.setScreenOrientation(SCREEN_ORIENTATION_BEHIND)
.build();
final int topOrientation = activityTop.getRequestedConfigurationOrientation();
- assertEquals(SCREEN_ORIENTATION_PORTRAIT, topOrientation);
+ assertEquals(ORIENTATION_PORTRAIT, topOrientation);
}
private void verifyProcessInfoUpdate(ActivityRecord activity, State state,
diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
index 7830e9094796..3a456fb9366c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
@@ -16,8 +16,9 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
@@ -79,24 +80,24 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
}
@Test
- public void testReturnsSkipIfTaskNotInFreeform() {
- final Task task = new TaskBuilder(mSupervisor).setWindowingMode(
- WINDOWING_MODE_FULLSCREEN).build();
+ public void testReturnsSkipIfTaskNotUsingActivityTypeStandard() {
+ final Task task = new TaskBuilder(mSupervisor).setActivityType(
+ ACTIVITY_TYPE_ASSISTANT).build();
assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(task).calculate());
}
@Test
public void testReturnsSkipIfCurrentParamsHasBounds() {
- final Task task = new TaskBuilder(mSupervisor).setWindowingMode(
- WINDOWING_MODE_FREEFORM).build();
+ final Task task = new TaskBuilder(mSupervisor).setActivityType(
+ ACTIVITY_TYPE_STANDARD).build();
mCurrent.mBounds.set(/* left */ 0, /* top */ 0, /* right */ 100, /* bottom */ 100);
assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(task).calculate());
}
@Test
public void testUsesDefaultBounds() {
- final Task task = new TaskBuilder(mSupervisor).setWindowingMode(
- WINDOWING_MODE_FREEFORM).build();
+ final Task task = new TaskBuilder(mSupervisor).setActivityType(
+ ACTIVITY_TYPE_STANDARD).build();
assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
assertEquals(dpiToPx(task, 840), mResult.mBounds.width());
assertEquals(dpiToPx(task, 630), mResult.mBounds.height());
@@ -104,8 +105,8 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
@Test
public void testUsesDisplayAreaAndWindowingModeFromSource() {
- final Task task = new TaskBuilder(mSupervisor).setWindowingMode(
- WINDOWING_MODE_FREEFORM).build();
+ final Task task = new TaskBuilder(mSupervisor).setActivityType(
+ ACTIVITY_TYPE_STANDARD).build();
TaskDisplayArea mockTaskDisplayArea = mock(TaskDisplayArea.class);
mCurrent.mPreferredTaskDisplayArea = mockTaskDisplayArea;
mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
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 de84655986ef..d77b6ada268e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -113,6 +113,8 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
/**
* Tests for Size Compatibility mode.
@@ -168,6 +170,156 @@ public class SizeCompatTests extends WindowTestsBase {
}
@Test
+ public void testHorizontalReachabilityEnabledForTranslucentActivities() {
+ setUpDisplaySizeWithApp(2500, 1000);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ final LetterboxConfiguration config = mWm.mLetterboxConfiguration;
+ config.setTranslucentLetterboxingOverrideEnabled(true);
+ config.setLetterboxHorizontalPositionMultiplier(0.5f);
+ config.setIsHorizontalReachabilityEnabled(true);
+
+ // Opaque activity
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+ addWindowToActivity(mActivity);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+
+ // Translucent Activity
+ final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+ .setLaunchedFromUid(mActivity.getUid())
+ .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+ .build();
+ doReturn(false).when(translucentActivity).fillsParent();
+ mTask.addChild(translucentActivity);
+
+ spyOn(translucentActivity.mLetterboxUiController);
+ doReturn(true).when(translucentActivity.mLetterboxUiController)
+ .shouldShowLetterboxUi(any());
+
+ addWindowToActivity(translucentActivity);
+ translucentActivity.mRootWindowContainer.performSurfacePlacement();
+
+ final Function<ActivityRecord, Rect> innerBoundsOf =
+ (ActivityRecord a) -> {
+ final Rect bounds = new Rect();
+ a.mLetterboxUiController.getLetterboxInnerBounds(bounds);
+ return bounds;
+ };
+ final Runnable checkLetterboxPositions = () -> assertEquals(innerBoundsOf.apply(mActivity),
+ innerBoundsOf.apply(translucentActivity));
+ final Runnable checkIsLeft = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).left).isEqualTo(0);
+ final Runnable checkIsRight = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).right).isEqualTo(2500);
+ final Runnable checkIsCentered = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).left > 0
+ && innerBoundsOf.apply(translucentActivity).right < 2500).isTrue();
+
+ final Consumer<Integer> doubleClick =
+ (Integer x) -> {
+ mActivity.mLetterboxUiController.handleHorizontalDoubleTap(x);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+ };
+
+ // Initial state
+ checkIsCentered.run();
+
+ // Double-click left
+ doubleClick.accept(/* x */ 10);
+ checkLetterboxPositions.run();
+ checkIsLeft.run();
+
+ // Double-click right
+ doubleClick.accept(/* x */ 1990);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+
+ // Double-click right
+ doubleClick.accept(/* x */ 1990);
+ checkLetterboxPositions.run();
+ checkIsRight.run();
+
+ // Double-click left
+ doubleClick.accept(/* x */ 10);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+ }
+
+ @Test
+ public void testVerticalReachabilityEnabledForTranslucentActivities() {
+ setUpDisplaySizeWithApp(1000, 2500);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ final LetterboxConfiguration config = mWm.mLetterboxConfiguration;
+ config.setTranslucentLetterboxingOverrideEnabled(true);
+ config.setLetterboxVerticalPositionMultiplier(0.5f);
+ config.setIsVerticalReachabilityEnabled(true);
+
+ // Opaque activity
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
+ addWindowToActivity(mActivity);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+
+ // Translucent Activity
+ final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+ .setLaunchedFromUid(mActivity.getUid())
+ .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE)
+ .build();
+ doReturn(false).when(translucentActivity).fillsParent();
+ mTask.addChild(translucentActivity);
+
+ spyOn(translucentActivity.mLetterboxUiController);
+ doReturn(true).when(translucentActivity.mLetterboxUiController)
+ .shouldShowLetterboxUi(any());
+
+ addWindowToActivity(translucentActivity);
+ translucentActivity.mRootWindowContainer.performSurfacePlacement();
+
+ final Function<ActivityRecord, Rect> innerBoundsOf =
+ (ActivityRecord a) -> {
+ final Rect bounds = new Rect();
+ a.mLetterboxUiController.getLetterboxInnerBounds(bounds);
+ return bounds;
+ };
+ final Runnable checkLetterboxPositions = () -> assertEquals(innerBoundsOf.apply(mActivity),
+ innerBoundsOf.apply(translucentActivity));
+ final Runnable checkIsTop = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).top).isEqualTo(0);
+ final Runnable checkIsBottom = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).bottom).isEqualTo(2500);
+ final Runnable checkIsCentered = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).top > 0
+ && innerBoundsOf.apply(translucentActivity).bottom < 2500).isTrue();
+
+ final Consumer<Integer> doubleClick =
+ (Integer y) -> {
+ mActivity.mLetterboxUiController.handleVerticalDoubleTap(y);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+ };
+
+ // Initial state
+ checkIsCentered.run();
+
+ // Double-click top
+ doubleClick.accept(/* y */ 10);
+ checkLetterboxPositions.run();
+ checkIsTop.run();
+
+ // Double-click bottom
+ doubleClick.accept(/* y */ 1990);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+
+ // Double-click bottom
+ doubleClick.accept(/* y */ 1990);
+ checkLetterboxPositions.run();
+ checkIsBottom.run();
+
+ // Double-click top
+ doubleClick.accept(/* y */ 10);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+ }
+
+ @Test
public void testApplyStrategyToTranslucentActivities() {
mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
setUpDisplaySizeWithApp(2000, 1000);
@@ -229,7 +381,7 @@ public class SizeCompatTests extends WindowTestsBase {
}
@Test
- public void testTranslucentActivitiesDontGoInSizeCompactMode() {
+ public void testTranslucentActivitiesDontGoInSizeCompatMode() {
mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
setUpDisplaySizeWithApp(2800, 1400);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
@@ -274,7 +426,8 @@ public class SizeCompatTests extends WindowTestsBase {
public void testTranslucentActivitiesWhenUnfolding() {
mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
setUpDisplaySizeWithApp(2800, 1400);
- mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(
+ true /* ignoreOrientationRequest */);
mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(
1.0f /*letterboxVerticalPositionMultiplier*/);
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
@@ -285,18 +438,23 @@ public class SizeCompatTests extends WindowTestsBase {
.build();
doReturn(false).when(translucentActivity).fillsParent();
mTask.addChild(translucentActivity);
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
spyOn(mActivity);
// Halffold
- setFoldablePosture(translucentActivity, true /* isHalfFolded */, false /* isTabletop */);
+ setFoldablePosture(translucentActivity, true /* isHalfFolded */,
+ false /* isTabletop */);
verify(mActivity).recomputeConfiguration();
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
clearInvocations(mActivity);
// Unfold
- setFoldablePosture(translucentActivity, false /* isHalfFolded */, false /* isTabletop */);
+ setFoldablePosture(translucentActivity, false /* isHalfFolded */,
+ false /* isTabletop */);
verify(mActivity).recomputeConfiguration();
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
}
@Test
@@ -803,7 +961,7 @@ public class SizeCompatTests extends WindowTestsBase {
.setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
.setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
.build();
- assertFalse(activity.shouldCreateCompatDisplayInsets());
+ assertTrue(activity.shouldCreateCompatDisplayInsets());
// The non-resizable activity should not be size compat because it is on a resizable task
// in multi-window mode.
@@ -836,7 +994,7 @@ public class SizeCompatTests extends WindowTestsBase {
}
@Test
- public void testShouldNotCreateCompatDisplayInsetsWhenRootActivityIsResizeable() {
+ public void testShouldCreateCompatDisplayInsetsWhenUnresizeableAndSupportsSizeChangesFalse() {
setUpDisplaySizeWithApp(1000, 2500);
// Make the task root resizable.
@@ -845,7 +1003,7 @@ public class SizeCompatTests extends WindowTestsBase {
// Create an activity on the same task.
final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- assertFalse(activity.shouldCreateCompatDisplayInsets());
+ assertTrue(activity.shouldCreateCompatDisplayInsets());
}
@Test
@@ -2296,11 +2454,11 @@ public class SizeCompatTests extends WindowTestsBase {
assertFalse(mActivity.inSizeCompatMode());
mActivity.setRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
-
- assertTrue(mActivity.inSizeCompatMode());
- // We should remember the original orientation.
+ // Activity is not in size compat mode because the orientation change request came from the
+ // app itself
+ assertFalse(mActivity.inSizeCompatMode());
assertEquals(mActivity.getResolvedOverrideConfiguration().orientation,
- Configuration.ORIENTATION_PORTRAIT);
+ Configuration.ORIENTATION_UNDEFINED);
}
@Test
@@ -2875,6 +3033,25 @@ public class SizeCompatTests extends WindowTestsBase {
}
@Test
+ public void testAppRequestsOrientationChange_notInSizeCompat() {
+ setUpDisplaySizeWithApp(2200, 1800);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
+
+ mActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
+
+ // Activity is not in size compat mode because the orientation change request came from the
+ // app itself
+ assertFalse(mActivity.inSizeCompatMode());
+
+ rotateDisplay(mActivity.mDisplayContent, ROTATION_270);
+ // Activity should go into size compat mode now because the orientation change came from the
+ // system (device rotation)
+ assertTrue(mActivity.inSizeCompatMode());
+ }
+
+ @Test
public void testLetterboxDetailsForStatusBar_noLetterbox() {
setUpDisplaySizeWithApp(2800, 1000);
addStatusBar(mActivity.mDisplayContent);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index c8932550d877..132aa90f1367 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -24,6 +24,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
@@ -603,4 +604,34 @@ public class TaskFragmentTest extends WindowTestsBase {
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, tf1.getOrientation(SCREEN_ORIENTATION_UNSET));
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, task.getOrientation(SCREEN_ORIENTATION_UNSET));
}
+
+ @Test
+ public void testUpdateImeParentForActivityEmbedding() {
+ // Setup two activities in ActivityEmbedding.
+ final Task task = createTask(mDisplayContent);
+ final TaskFragment tf0 = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .createActivityCount(1)
+ .setOrganizer(mOrganizer)
+ .setFragmentToken(new Binder())
+ .build();
+ final TaskFragment tf1 = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .createActivityCount(1)
+ .setOrganizer(mOrganizer)
+ .setFragmentToken(new Binder())
+ .build();
+ final ActivityRecord activity0 = tf0.getTopMostActivity();
+ final ActivityRecord activity1 = tf1.getTopMostActivity();
+ final WindowState win0 = createWindow(null, TYPE_BASE_APPLICATION, activity0, "win0");
+ final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity1, "win1");
+ doReturn(false).when(mDisplayContent).shouldImeAttachedToApp();
+
+ mDisplayContent.setImeInputTarget(win0);
+ mDisplayContent.setImeLayeringTarget(win1);
+
+ // The ImeParent should be the display.
+ assertEquals(mDisplayContent.getImeContainer().getParent().getSurfaceControl(),
+ mDisplayContent.computeImeParent());
+ }
}
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 1407cdd8600c..65f31a0e15bb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -52,6 +52,7 @@ import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.util.MergedConfiguration;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
@@ -61,6 +62,7 @@ import android.view.RoundedCorners;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowManager;
+import android.window.ClientWindowFrames;
import androidx.test.filters.SmallTest;
@@ -338,6 +340,29 @@ public class WallpaperControllerTests extends WindowTestsBase {
}
@Test
+ public void testWallpaperReportConfigChange() {
+ final WindowState wallpaperWindow = createWallpaperWindow(mDisplayContent);
+ createWallpaperTargetWindow(mDisplayContent);
+ final WallpaperWindowToken wallpaperToken = wallpaperWindow.mToken.asWallpaperToken();
+ makeWindowVisible(wallpaperWindow);
+ wallpaperWindow.mLayoutSeq = mDisplayContent.mLayoutSeq;
+ // Assume the token was invisible and the latest config was reported.
+ wallpaperToken.commitVisibility(false);
+ wallpaperWindow.fillClientWindowFramesAndConfiguration(new ClientWindowFrames(),
+ new MergedConfiguration(), true /* useLatestConfig */, false /* relayoutVisible */);
+ assertTrue(wallpaperWindow.isLastConfigReportedToClient());
+
+ final Rect bounds = wallpaperToken.getBounds();
+ wallpaperToken.setBounds(new Rect(0, 0, bounds.width() / 2, bounds.height() / 2));
+ assertFalse(wallpaperWindow.isLastConfigReportedToClient());
+ // If there is a pending config change when changing to visible, it should tell the client
+ // to redraw by WindowState#reportResized.
+ wallpaperToken.commitVisibility(true);
+ waitUntilHandlersIdle();
+ assertTrue(wallpaperWindow.isLastConfigReportedToClient());
+ }
+
+ @Test
public void testWallpaperTokenVisibility() {
final DisplayContent dc = mWm.mRoot.getDefaultDisplay();
final WindowState wallpaperWindow = createWallpaperWindow(dc);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 6ea416b54811..468bf1719d89 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -510,7 +510,6 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
private boolean mUsbAccessoryConnected;
private boolean mSourcePower;
private boolean mSinkPower;
- private boolean mConfigured;
private boolean mAudioAccessoryConnected;
private boolean mAudioAccessorySupported;
@@ -543,7 +542,12 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
private final UsbPermissionManager mPermissionManager;
private NotificationManager mNotificationManager;
+ /**
+ * Do not debounce for the first disconnect after resetUsbGadget.
+ */
+ protected boolean mResetUsbGadgetDisableDebounce;
protected boolean mConnected;
+ protected boolean mConfigured;
protected long mScreenUnlockedFunctions;
protected boolean mBootCompleted;
protected boolean mCurrentFunctionsApplied;
@@ -650,15 +654,29 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
Slog.e(TAG, "unknown state " + state);
return;
}
- if (configured == 0) removeMessages(MSG_UPDATE_STATE);
if (connected == 1) removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT);
Message msg = Message.obtain(this, MSG_UPDATE_STATE);
msg.arg1 = connected;
msg.arg2 = configured;
- // debounce disconnects to avoid problems bringing up USB tethering
- sendMessageDelayed(msg,
+ if (DEBUG) {
+ Slog.i(TAG, "mResetUsbGadgetDisableDebounce:" + mResetUsbGadgetDisableDebounce
+ + " connected:" + connected + "configured:" + configured);
+ }
+ if (mResetUsbGadgetDisableDebounce) {
+ // Do not debounce disconnect after resetUsbGadget.
+ sendMessage(msg);
+ if (connected == 1) mResetUsbGadgetDisableDebounce = false;
+ } else {
+ if (configured == 0) {
+ removeMessages(MSG_UPDATE_STATE);
+ if (DEBUG) Slog.i(TAG, "removeMessages MSG_UPDATE_STATE");
+ }
+ if (connected == 1) removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT);
+ // debounce disconnects to avoid problems bringing up USB tethering.
+ sendMessageDelayed(msg,
(connected == 0) ? (mScreenLocked ? DEVICE_STATE_UPDATE_DELAY
: DEVICE_STATE_UPDATE_DELAY_EXT) : 0);
+ }
}
public void updateHostState(UsbPort port, UsbPortStatus status) {
@@ -904,7 +922,10 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
case MSG_UPDATE_STATE:
mConnected = (msg.arg1 == 1);
mConfigured = (msg.arg2 == 1);
-
+ if (DEBUG) {
+ Slog.i(TAG, "handleMessage MSG_UPDATE_STATE " + "mConnected:" + mConnected
+ + " mConfigured:" + mConfigured);
+ }
updateUsbNotification(false);
updateAdbNotification(false);
if (mBootCompleted) {
@@ -2010,12 +2031,19 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
}
try {
+ // MSG_ACCESSORY_MODE_ENTER_TIMEOUT has to be removed to allow exiting
+ // AOAP mode during resetUsbGadget.
+ removeMessages(MSG_ACCESSORY_MODE_ENTER_TIMEOUT);
+ if (mConfigured) {
+ mResetUsbGadgetDisableDebounce = true;
+ }
android.hardware.usb.gadget.V1_1.IUsbGadget gadgetProxy =
android.hardware.usb.gadget.V1_1.IUsbGadget
.castFrom(mGadgetProxy);
gadgetProxy.reset();
} catch (RemoteException e) {
Slog.e(TAG, "reset Usb Gadget failed", e);
+ mResetUsbGadgetDisableDebounce = false;
}
}
break;
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index ec18c6a696b8..7a53447c1eee 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -555,6 +555,11 @@ public final class PhoneAccount implements Parcelable {
/**
* Sets the address. See {@link PhoneAccount#getAddress}.
+ * <p>
+ * Note: The entire URI value is limited to 256 characters. This check is
+ * enforced when registering the PhoneAccount via
+ * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an
+ * {@link IllegalArgumentException} to be thrown if URI is over 256.
*
* @param value The address of the phone account.
* @return The builder.
@@ -588,6 +593,10 @@ public final class PhoneAccount implements Parcelable {
/**
* Sets the icon. See {@link PhoneAccount#getIcon}.
+ * <p>
+ * Note: An {@link IllegalArgumentException} if the Icon cannot be written to memory.
+ * This check is enforced when registering the PhoneAccount via
+ * {@link TelecomManager#registerPhoneAccount(PhoneAccount)}
*
* @param icon The icon to set.
*/
@@ -621,6 +630,10 @@ public final class PhoneAccount implements Parcelable {
/**
* Specifies an additional URI scheme supported by the {@link PhoneAccount}.
*
+ * <p>
+ * Each URI scheme is limited to 256 characters. Adding a scheme over 256 characters will
+ * cause an {@link IllegalArgumentException} to be thrown when the account is registered.
+ *
* @param uriScheme The URI scheme.
* @return The builder.
*/
@@ -634,6 +647,12 @@ public final class PhoneAccount implements Parcelable {
/**
* Specifies the URI schemes supported by the {@link PhoneAccount}.
*
+ * <p>
+ * A max of 10 URI schemes can be added per account. Additionally, each URI scheme is
+ * limited to 256 characters. Adding more than 10 URI schemes or 256 characters on any
+ * scheme will cause an {@link IllegalArgumentException} to be thrown when the account
+ * is registered.
+ *
* @param uriSchemes The URI schemes.
* @return The builder.
*/
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
index a8cbc5dc922c..e05312fe8cc5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
@@ -18,12 +18,15 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.RequiresDevice
+import android.platform.test.rule.SettingOverrideRule
+import android.provider.Settings
import androidx.test.filters.FlakyTest
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import org.junit.ClassRule
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -98,5 +101,16 @@ open class OpenAppFromLockNotificationCold(testSpec: FlickerTestParameter)
return com.android.server.wm.flicker.FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(repetitions = 3)
}
+
+ /**
+ * Ensures that posted notifications will be visible on the lockscreen and not
+ * suppressed due to being marked as seen.
+ */
+ @ClassRule
+ @JvmField
+ val disableUnseenNotifFilterRule = SettingOverrideRule(
+ Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS,
+ /* value= */ "0",
+ )
}
-} \ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
index cd8dea012db5..fcec79f4d7f5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
@@ -18,6 +18,8 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.RequiresDevice
+import android.platform.test.rule.SettingOverrideRule
+import android.provider.Settings
import androidx.test.filters.FlakyTest
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
@@ -25,6 +27,7 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.ClassRule
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -124,5 +127,16 @@ open class OpenAppFromLockNotificationWarm(testSpec: FlickerTestParameter)
return com.android.server.wm.flicker.FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(repetitions = 3)
}
+
+ /**
+ * Ensures that posted notifications will be visible on the lockscreen and not
+ * suppressed due to being marked as seen.
+ */
+ @ClassRule
+ @JvmField
+ val disableUnseenNotifFilterRule = SettingOverrideRule(
+ Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS,
+ /* value= */ "0",
+ )
}
-} \ No newline at end of file
+}
diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
index 3db011683a86..fdd919412e55 100644
--- a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
@@ -86,7 +86,7 @@ public class ProtoLogImplTest {
mFile = testContext.getFileStreamPath("tracing_test.dat");
//noinspection ResultOfMethodCallIgnored
mFile.delete();
- mProtoLog = new ProtoLogImpl(mFile, 1024 * 1024, mReader);
+ mProtoLog = new ProtoLogImpl(mFile, 1024 * 1024, mReader, 1024);
}
@After
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index 34e8edb0a47f..8ea43abff895 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -27,7 +27,7 @@ namespace aapt {
static ApiVersion sDevelopmentSdkLevel = 10000;
static const auto sDevelopmentSdkCodeNames =
- std::unordered_set<StringPiece>({"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake"});
+ std::unordered_set<StringPiece>({"Q", "R", "S", "Sv2", "Tiramisu"});
static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = {
{0x021c, 1},